@chainsafe/lodestar 1.35.0-dev.8cacf063da → 1.35.0-dev.901d719660
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.
- package/.git-data.json +1 -1
- package/bin/lodestar.js +3 -0
- package/bin/lodestar.ts +3 -0
- package/lib/applyPreset.d.ts.map +1 -0
- package/lib/cli.d.ts +3 -3
- package/lib/cli.d.ts.map +1 -0
- package/lib/cli.js +1 -1
- package/lib/cli.js.map +1 -1
- package/lib/cmds/beacon/handler.d.ts +1 -1
- package/lib/cmds/beacon/handler.d.ts.map +1 -0
- package/lib/cmds/beacon/handler.js +1 -1
- package/lib/cmds/beacon/handler.js.map +1 -1
- package/lib/cmds/beacon/index.d.ts.map +1 -0
- package/lib/cmds/beacon/initBeaconState.d.ts.map +1 -0
- package/lib/cmds/beacon/initBeaconState.js.map +1 -1
- package/lib/cmds/beacon/initPeerIdAndEnr.d.ts +2 -2
- package/lib/cmds/beacon/initPeerIdAndEnr.d.ts.map +1 -0
- package/lib/cmds/beacon/initPeerIdAndEnr.js +1 -1
- package/lib/cmds/beacon/initPeerIdAndEnr.js.map +1 -1
- package/lib/cmds/beacon/options.d.ts.map +1 -0
- package/lib/cmds/beacon/paths.d.ts.map +1 -0
- package/lib/cmds/bootnode/handler.d.ts +13 -8
- package/lib/cmds/bootnode/handler.d.ts.map +1 -0
- package/lib/cmds/bootnode/handler.js +2 -2
- package/lib/cmds/bootnode/handler.js.map +1 -1
- package/lib/cmds/bootnode/index.d.ts.map +1 -0
- package/lib/cmds/bootnode/options.d.ts.map +1 -0
- package/lib/cmds/bootnode/options.js +2 -1
- package/lib/cmds/bootnode/options.js.map +1 -1
- package/lib/cmds/dev/files.d.ts.map +1 -0
- package/lib/cmds/dev/handler.d.ts.map +1 -0
- package/lib/cmds/dev/handler.js +1 -1
- package/lib/cmds/dev/handler.js.map +1 -1
- package/lib/cmds/dev/index.d.ts.map +1 -0
- package/lib/cmds/dev/options.d.ts.map +1 -0
- package/lib/cmds/index.d.ts.map +1 -0
- package/lib/cmds/lightclient/handler.d.ts.map +1 -0
- package/lib/cmds/lightclient/index.d.ts.map +1 -0
- package/lib/cmds/lightclient/options.d.ts.map +1 -0
- package/lib/cmds/validator/blsToExecutionChange.d.ts.map +1 -0
- package/lib/cmds/validator/blsToExecutionChange.js.map +1 -1
- package/lib/cmds/validator/handler.d.ts.map +1 -0
- package/lib/cmds/validator/handler.js +3 -5
- package/lib/cmds/validator/handler.js.map +1 -1
- package/lib/cmds/validator/import.d.ts.map +1 -0
- package/lib/cmds/validator/index.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/decryptKeystoreDefinitions.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/decryptKeystores/index.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/decryptKeystores/poolSize.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/decryptKeystores/threadPool.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/decryptKeystores/threadPool.js +4 -1
- package/lib/cmds/validator/keymanager/decryptKeystores/threadPool.js.map +1 -1
- package/lib/cmds/validator/keymanager/decryptKeystores/types.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/decryptKeystores/worker.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/impl.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/impl.js +4 -0
- package/lib/cmds/validator/keymanager/impl.js.map +1 -1
- package/lib/cmds/validator/keymanager/interface.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/keystoreCache.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/persistedKeys.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/persistedKeys.js +1 -0
- package/lib/cmds/validator/keymanager/persistedKeys.js.map +1 -1
- package/lib/cmds/validator/keymanager/server.d.ts.map +1 -0
- package/lib/cmds/validator/keymanager/server.js +2 -0
- package/lib/cmds/validator/keymanager/server.js.map +1 -1
- package/lib/cmds/validator/list.d.ts.map +1 -0
- package/lib/cmds/validator/options.d.ts.map +1 -0
- package/lib/cmds/validator/options.js +2 -2
- package/lib/cmds/validator/paths.d.ts.map +1 -0
- package/lib/cmds/validator/signers/importExternalKeystores.d.ts.map +1 -0
- package/lib/cmds/validator/signers/index.d.ts.map +1 -0
- package/lib/cmds/validator/signers/logSigners.d.ts.map +1 -0
- package/lib/cmds/validator/slashingProtection/export.d.ts.map +1 -0
- package/lib/cmds/validator/slashingProtection/import.d.ts.map +1 -0
- package/lib/cmds/validator/slashingProtection/index.d.ts.map +1 -0
- package/lib/cmds/validator/slashingProtection/options.d.ts.map +1 -0
- package/lib/cmds/validator/slashingProtection/utils.d.ts.map +1 -0
- package/lib/cmds/validator/slashingProtection/utils.js +1 -1
- package/lib/cmds/validator/slashingProtection/utils.js.map +1 -1
- package/lib/cmds/validator/voluntaryExit.d.ts.map +1 -0
- package/lib/cmds/validator/voluntaryExit.js +1 -1
- package/lib/cmds/validator/voluntaryExit.js.map +1 -1
- package/lib/config/beaconNodeOptions.d.ts.map +1 -0
- package/lib/config/beaconNodeOptions.js +2 -1
- package/lib/config/beaconNodeOptions.js.map +1 -1
- package/lib/config/beaconParams.d.ts.map +1 -0
- package/lib/config/index.d.ts.map +1 -0
- package/lib/config/peerId.d.ts.map +1 -0
- package/lib/config/types.d.ts.map +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js.map +1 -1
- package/lib/migrations/index.d.ts +1 -0
- package/lib/migrations/index.d.ts.map +1 -0
- package/lib/migrations/index.js +1 -1
- package/lib/networks/chiado.d.ts.map +1 -0
- package/lib/networks/dev.d.ts.map +1 -0
- package/lib/networks/ephemery.d.ts.map +1 -0
- package/lib/networks/gnosis.d.ts.map +1 -0
- package/lib/networks/holesky.d.ts.map +1 -0
- package/lib/networks/hoodi.d.ts.map +1 -0
- package/lib/networks/index.d.ts.map +1 -0
- package/lib/networks/index.js +1 -2
- package/lib/networks/index.js.map +1 -1
- package/lib/networks/mainnet.d.ts.map +1 -0
- package/lib/networks/sepolia.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/api.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/builder.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/chain.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/eth1.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/execution.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/index.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/metrics.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/monitoring.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/network.d.ts +1 -0
- package/lib/options/beaconNodeOptions/network.d.ts.map +1 -0
- package/lib/options/beaconNodeOptions/network.js +6 -3
- package/lib/options/beaconNodeOptions/network.js.map +1 -1
- package/lib/options/beaconNodeOptions/sync.d.ts.map +1 -0
- package/lib/options/globalOptions.d.ts.map +1 -0
- package/lib/options/index.d.ts.map +1 -0
- package/lib/options/logOptions.d.ts.map +1 -0
- package/lib/options/paramsOptions.d.ts.map +1 -0
- package/lib/paths/global.d.ts.map +1 -0
- package/lib/paths/rootDir.d.ts.map +1 -0
- package/lib/util/errors.d.ts.map +1 -0
- package/lib/util/ethers.d.ts.map +1 -0
- package/lib/util/feeRecipient.d.ts.map +1 -0
- package/lib/util/file.d.ts.map +1 -0
- package/lib/util/file.js +1 -1
- package/lib/util/file.js.map +1 -1
- package/lib/util/format.d.ts.map +1 -0
- package/lib/util/fs.d.ts.map +1 -0
- package/lib/util/gitData/gitDataPath.d.ts.map +1 -0
- package/lib/util/gitData/index.d.ts.map +1 -0
- package/lib/util/gitData/index.js.map +1 -1
- package/lib/util/gitData/writeGitData.d.ts.map +1 -0
- package/lib/util/index.d.ts +3 -3
- package/lib/util/index.d.ts.map +1 -0
- package/lib/util/index.js +3 -3
- package/lib/util/index.js.map +1 -1
- package/lib/util/jwt.d.ts.map +1 -0
- package/lib/util/lockfile.d.ts.map +1 -0
- package/lib/util/logger.d.ts.map +1 -0
- package/lib/util/logger.js +1 -1
- package/lib/util/logger.js.map +1 -1
- package/lib/util/object.d.ts.map +1 -0
- package/lib/util/object.js.map +1 -1
- package/lib/util/passphrase.d.ts.map +1 -0
- package/lib/util/process.d.ts.map +1 -0
- package/lib/util/progress.d.ts.map +1 -0
- package/lib/util/proposerConfig.d.ts.map +1 -0
- package/lib/util/proposerConfig.js.map +1 -1
- package/lib/util/pruneOldFilesInDir.d.ts.map +1 -0
- package/lib/util/sleep.d.ts.map +1 -0
- package/lib/util/stripOffNewlines.d.ts.map +1 -0
- package/lib/util/types.d.ts.map +1 -0
- package/lib/util/version.d.ts.map +1 -0
- package/package.json +20 -19
- package/src/applyPreset.ts +91 -0
- package/src/cli.ts +56 -0
- package/src/cmds/beacon/handler.ts +267 -0
- package/src/cmds/beacon/index.ts +18 -0
- package/src/cmds/beacon/initBeaconState.ts +275 -0
- package/src/cmds/beacon/initPeerIdAndEnr.ts +199 -0
- package/src/cmds/beacon/options.ts +214 -0
- package/src/cmds/beacon/paths.ts +62 -0
- package/src/cmds/bootnode/handler.ts +203 -0
- package/src/cmds/bootnode/index.ts +13 -0
- package/src/cmds/bootnode/options.ts +109 -0
- package/src/cmds/dev/files.ts +52 -0
- package/src/cmds/dev/handler.ts +86 -0
- package/src/cmds/dev/index.ts +18 -0
- package/src/cmds/dev/options.ts +110 -0
- package/src/cmds/index.ts +15 -0
- package/src/cmds/lightclient/handler.ts +36 -0
- package/src/cmds/lightclient/index.ts +18 -0
- package/src/cmds/lightclient/options.ts +21 -0
- package/src/cmds/validator/blsToExecutionChange.ts +91 -0
- package/src/cmds/validator/handler.ts +300 -0
- package/src/cmds/validator/import.ts +111 -0
- package/src/cmds/validator/index.ts +28 -0
- package/src/cmds/validator/keymanager/decryptKeystoreDefinitions.ts +189 -0
- package/src/cmds/validator/keymanager/decryptKeystores/index.ts +1 -0
- package/src/cmds/validator/keymanager/decryptKeystores/poolSize.ts +16 -0
- package/src/cmds/validator/keymanager/decryptKeystores/threadPool.ts +75 -0
- package/src/cmds/validator/keymanager/decryptKeystores/types.ts +12 -0
- package/src/cmds/validator/keymanager/decryptKeystores/worker.ts +24 -0
- package/src/cmds/validator/keymanager/impl.ts +425 -0
- package/src/cmds/validator/keymanager/interface.ts +35 -0
- package/src/cmds/validator/keymanager/keystoreCache.ts +91 -0
- package/src/cmds/validator/keymanager/persistedKeys.ts +268 -0
- package/src/cmds/validator/keymanager/server.ts +86 -0
- package/src/cmds/validator/list.ts +35 -0
- package/src/cmds/validator/options.ts +461 -0
- package/src/cmds/validator/paths.ts +95 -0
- package/src/cmds/validator/signers/importExternalKeystores.ts +69 -0
- package/src/cmds/validator/signers/index.ts +176 -0
- package/src/cmds/validator/signers/logSigners.ts +81 -0
- package/src/cmds/validator/slashingProtection/export.ts +110 -0
- package/src/cmds/validator/slashingProtection/import.ts +70 -0
- package/src/cmds/validator/slashingProtection/index.ts +12 -0
- package/src/cmds/validator/slashingProtection/options.ts +15 -0
- package/src/cmds/validator/slashingProtection/utils.ts +56 -0
- package/src/cmds/validator/voluntaryExit.ts +232 -0
- package/src/config/beaconNodeOptions.ts +68 -0
- package/src/config/beaconParams.ts +87 -0
- package/src/config/index.ts +3 -0
- package/src/config/peerId.ts +50 -0
- package/src/config/types.ts +3 -0
- package/src/index.ts +28 -0
- package/src/migrations/index.ts +0 -0
- package/src/networks/chiado.ts +20 -0
- package/src/networks/dev.ts +27 -0
- package/src/networks/ephemery.ts +9 -0
- package/src/networks/gnosis.ts +18 -0
- package/src/networks/holesky.ts +17 -0
- package/src/networks/hoodi.ts +16 -0
- package/src/networks/index.ts +236 -0
- package/src/networks/mainnet.ts +34 -0
- package/src/networks/sepolia.ts +17 -0
- package/src/options/beaconNodeOptions/api.ts +110 -0
- package/src/options/beaconNodeOptions/builder.ts +63 -0
- package/src/options/beaconNodeOptions/chain.ts +326 -0
- package/src/options/beaconNodeOptions/eth1.ts +95 -0
- package/src/options/beaconNodeOptions/execution.ts +92 -0
- package/src/options/beaconNodeOptions/index.ts +50 -0
- package/src/options/beaconNodeOptions/metrics.ts +39 -0
- package/src/options/beaconNodeOptions/monitoring.ts +61 -0
- package/src/options/beaconNodeOptions/network.ts +401 -0
- package/src/options/beaconNodeOptions/sync.ts +65 -0
- package/src/options/globalOptions.ts +72 -0
- package/src/options/index.ts +3 -0
- package/src/options/logOptions.ts +70 -0
- package/src/options/paramsOptions.ts +72 -0
- package/src/paths/global.ts +24 -0
- package/src/paths/rootDir.ts +11 -0
- package/src/util/errors.ts +20 -0
- package/src/util/ethers.ts +44 -0
- package/src/util/feeRecipient.ts +6 -0
- package/src/util/file.ts +167 -0
- package/src/util/format.ts +76 -0
- package/src/util/fs.ts +59 -0
- package/src/util/gitData/gitDataPath.ts +48 -0
- package/src/util/gitData/index.ts +70 -0
- package/src/util/gitData/writeGitData.ts +10 -0
- package/src/util/index.ts +17 -0
- package/src/util/jwt.ts +10 -0
- package/src/util/lockfile.ts +45 -0
- package/src/util/logger.ts +105 -0
- package/src/util/object.ts +15 -0
- package/src/util/passphrase.ts +25 -0
- package/src/util/process.ts +25 -0
- package/src/util/progress.ts +58 -0
- package/src/util/proposerConfig.ts +136 -0
- package/src/util/pruneOldFilesInDir.ts +27 -0
- package/src/util/sleep.ts +3 -0
- package/src/util/stripOffNewlines.ts +6 -0
- package/src/util/types.ts +8 -0
- package/src/util/version.ts +74 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import {CliCommandOptions, CliOptionDefinition} from "@lodestar/utils";
|
|
2
|
+
import {MetricsArgs, options as metricsOptions} from "../../options/beaconNodeOptions/metrics.js";
|
|
3
|
+
import {defaultListenAddress, defaultListenAddress6, defaultP2pPort} from "../../options/beaconNodeOptions/network.js";
|
|
4
|
+
import {LogArgs, logOptions} from "../../options/logOptions.js";
|
|
5
|
+
|
|
6
|
+
type BootnodeExtraArgs = {
|
|
7
|
+
listenAddress?: string;
|
|
8
|
+
port?: number;
|
|
9
|
+
listenAddress6?: string;
|
|
10
|
+
port6?: number;
|
|
11
|
+
bootnodes?: string[];
|
|
12
|
+
bootnodesFile?: string;
|
|
13
|
+
persistNetworkIdentity?: boolean;
|
|
14
|
+
"enr.ip"?: string;
|
|
15
|
+
"enr.ip6"?: string;
|
|
16
|
+
"enr.udp"?: number;
|
|
17
|
+
"enr.udp6"?: number;
|
|
18
|
+
nat?: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const bootnodeExtraOptions: CliCommandOptions<BootnodeExtraArgs> = {
|
|
22
|
+
listenAddress: {
|
|
23
|
+
type: "string",
|
|
24
|
+
description: "The IPv4 address to listen for discv5 connections",
|
|
25
|
+
defaultDescription: defaultListenAddress,
|
|
26
|
+
group: "network",
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
port: {
|
|
30
|
+
alias: "discoveryPort",
|
|
31
|
+
description: "The UDP port to listen on",
|
|
32
|
+
type: "number",
|
|
33
|
+
defaultDescription: String(defaultP2pPort),
|
|
34
|
+
group: "network",
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
listenAddress6: {
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "The IPv6 address to listen for discv5 connections",
|
|
40
|
+
defaultDescription: defaultListenAddress6,
|
|
41
|
+
group: "network",
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
port6: {
|
|
45
|
+
alias: "discoveryPort6",
|
|
46
|
+
description: "The UDP port to listen on",
|
|
47
|
+
type: "number",
|
|
48
|
+
defaultDescription: String(defaultP2pPort),
|
|
49
|
+
group: "network",
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
bootnodes: {
|
|
53
|
+
type: "array",
|
|
54
|
+
description: "Additional bootnodes for discv5 discovery",
|
|
55
|
+
defaultDescription: JSON.stringify([]),
|
|
56
|
+
// Each bootnode entry could be comma separated, just deserialize it into a single array
|
|
57
|
+
// as comma separated entries are generally most friendly in ansible kind of setups, i.e.
|
|
58
|
+
// [ "en1", "en2,en3" ] => [ 'en1', 'en2', 'en3' ]
|
|
59
|
+
coerce: (args: string[]) => args.flatMap((item) => item.split(",")),
|
|
60
|
+
group: "network",
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
bootnodesFile: {
|
|
64
|
+
description: "Additional bootnodes for discv5 discovery file path",
|
|
65
|
+
type: "string",
|
|
66
|
+
group: "network",
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
persistNetworkIdentity: {
|
|
70
|
+
description: "Whether to reuse the same peer-id across restarts",
|
|
71
|
+
default: true,
|
|
72
|
+
type: "boolean",
|
|
73
|
+
group: "network",
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
"enr.ip": {
|
|
77
|
+
description: "Override ENR IP entry",
|
|
78
|
+
type: "string",
|
|
79
|
+
group: "enr",
|
|
80
|
+
},
|
|
81
|
+
"enr.udp": {
|
|
82
|
+
description: "Override ENR UDP entry",
|
|
83
|
+
type: "number",
|
|
84
|
+
group: "enr",
|
|
85
|
+
},
|
|
86
|
+
"enr.ip6": {
|
|
87
|
+
description: "Override ENR IPv6 entry",
|
|
88
|
+
type: "string",
|
|
89
|
+
group: "enr",
|
|
90
|
+
},
|
|
91
|
+
"enr.udp6": {
|
|
92
|
+
description: "Override ENR (IPv6-specific) UDP entry",
|
|
93
|
+
type: "number",
|
|
94
|
+
group: "enr",
|
|
95
|
+
},
|
|
96
|
+
nat: {
|
|
97
|
+
type: "boolean",
|
|
98
|
+
description: "Allow ENR configuration of non-local addresses",
|
|
99
|
+
group: "enr",
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export type BootnodeArgs = BootnodeExtraArgs & LogArgs & MetricsArgs;
|
|
104
|
+
|
|
105
|
+
export const bootnodeOptions: {[k: string]: CliOptionDefinition} = {
|
|
106
|
+
...bootnodeExtraOptions,
|
|
107
|
+
...logOptions,
|
|
108
|
+
...metricsOptions,
|
|
109
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {Keystore} from "@chainsafe/bls-keystore";
|
|
4
|
+
import {nodeUtils} from "@lodestar/beacon-node";
|
|
5
|
+
import {ChainForkConfig, chainConfigToJson} from "@lodestar/config";
|
|
6
|
+
import {interopSecretKey} from "@lodestar/state-transition";
|
|
7
|
+
import {dumpYaml} from "@lodestar/utils";
|
|
8
|
+
import {PersistedKeysBackend} from "../validator/keymanager/persistedKeys.js";
|
|
9
|
+
|
|
10
|
+
export async function writeTestnetFiles(
|
|
11
|
+
config: ChainForkConfig,
|
|
12
|
+
targetDir: string,
|
|
13
|
+
genesisValidators: number
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
const genesisTime = Math.floor(Date.now() / 1000);
|
|
16
|
+
const eth1BlockHash = Buffer.alloc(32, 0);
|
|
17
|
+
|
|
18
|
+
const {state} = nodeUtils.initDevState(config, genesisValidators, {genesisTime, eth1BlockHash});
|
|
19
|
+
|
|
20
|
+
// Write testnet data
|
|
21
|
+
fs.mkdirSync(targetDir, {recursive: true});
|
|
22
|
+
fs.writeFileSync(path.join(targetDir, "genesis.ssz"), state.serialize());
|
|
23
|
+
fs.writeFileSync(path.join(targetDir, "config.yaml"), dumpYaml(chainConfigToJson(config)));
|
|
24
|
+
fs.writeFileSync(path.join(targetDir, "deploy_block.txt"), "0");
|
|
25
|
+
|
|
26
|
+
const persistedKeystoresBackend = new PersistedKeysBackend({
|
|
27
|
+
keystoresDir: path.join(targetDir, "keystores"),
|
|
28
|
+
secretsDir: path.join(targetDir, "secrets"),
|
|
29
|
+
remoteKeysDir: path.join(targetDir, "remote_keys"),
|
|
30
|
+
proposerDir: path.join(targetDir, "proposer"),
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const password = "test_password";
|
|
34
|
+
|
|
35
|
+
// Write keystores
|
|
36
|
+
for (let i = 0; i < genesisValidators; i++) {
|
|
37
|
+
console.log(`Generating keystore ${i}`);
|
|
38
|
+
|
|
39
|
+
const sk = interopSecretKey(i);
|
|
40
|
+
|
|
41
|
+
const keystore = await Keystore.create(password, sk.toBytes(), sk.toPublicKey().toBytes(), "");
|
|
42
|
+
|
|
43
|
+
persistedKeystoresBackend.writeKeystore({
|
|
44
|
+
keystoreStr: keystore.stringify(),
|
|
45
|
+
password,
|
|
46
|
+
// Not used immediately
|
|
47
|
+
lockBeforeWrite: false,
|
|
48
|
+
// Return duplicate status if already found
|
|
49
|
+
persistIfDuplicate: false,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import {rimraf} from "rimraf";
|
|
3
|
+
import {nodeUtils} from "@lodestar/beacon-node";
|
|
4
|
+
import {fromHex, toHex} from "@lodestar/utils";
|
|
5
|
+
import {getBeaconConfigFromArgs} from "../../config/beaconParams.js";
|
|
6
|
+
import {GlobalArgs} from "../../options/index.js";
|
|
7
|
+
import {mkdir, onGracefulShutdown} from "../../util/index.js";
|
|
8
|
+
import {beaconHandler} from "../beacon/handler.js";
|
|
9
|
+
import {getBeaconPaths} from "../beacon/paths.js";
|
|
10
|
+
import {validatorHandler} from "../validator/handler.js";
|
|
11
|
+
import {getValidatorPaths} from "../validator/paths.js";
|
|
12
|
+
import {writeTestnetFiles} from "./files.js";
|
|
13
|
+
import {IDevArgs} from "./options.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Run a beacon node with validator
|
|
17
|
+
*/
|
|
18
|
+
export async function devHandler(args: IDevArgs & GlobalArgs): Promise<void> {
|
|
19
|
+
const {config} = getBeaconConfigFromArgs(args);
|
|
20
|
+
|
|
21
|
+
if (args.dumpTestnetFiles) {
|
|
22
|
+
await writeTestnetFiles(config, args.dumpTestnetFiles, args.genesisValidators);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// TODO: Is this necessary?
|
|
27
|
+
const network = "dev";
|
|
28
|
+
if (args.network && args.network !== network) {
|
|
29
|
+
throw Error(`Must not run dev command with network '${args.network}', only 'dev' network`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Note: defaults to network "dev", to all paths are custom and don't conflict with networks.
|
|
33
|
+
// Flag --reset cleans up the custom dirs on dev stop
|
|
34
|
+
const beaconDbDir = getBeaconPaths(args, network).dbDir;
|
|
35
|
+
const validatorsDbDir = getValidatorPaths(args, network).validatorsDbDir;
|
|
36
|
+
|
|
37
|
+
// Remove slashing protection db. Otherwise the validators won't be able to propose nor attest
|
|
38
|
+
// until the clock reach a higher slot than the previous run of the dev command
|
|
39
|
+
if (args.genesisTime === undefined) {
|
|
40
|
+
await rimraf(beaconDbDir);
|
|
41
|
+
await rimraf(validatorsDbDir);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
mkdir(beaconDbDir);
|
|
45
|
+
mkdir(validatorsDbDir);
|
|
46
|
+
|
|
47
|
+
if (args.reset) {
|
|
48
|
+
onGracefulShutdown(async () => {
|
|
49
|
+
await rimraf(beaconDbDir);
|
|
50
|
+
await rimraf(validatorsDbDir);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// To be able to recycle beacon handler pass the genesis state via file
|
|
55
|
+
if (args.genesisStateFile) {
|
|
56
|
+
// Already set, skip
|
|
57
|
+
} else {
|
|
58
|
+
// Generate and write state to disk
|
|
59
|
+
const validatorCount = args.genesisValidators ?? 8;
|
|
60
|
+
const genesisTime = args.genesisTime ?? Math.floor(Date.now() / 1000) + 5;
|
|
61
|
+
const eth1BlockHash = fromHex(args.genesisEth1Hash ?? toHex(Buffer.alloc(32, 0x0b)));
|
|
62
|
+
|
|
63
|
+
const {state} = nodeUtils.initDevState(config, validatorCount, {genesisTime, eth1BlockHash});
|
|
64
|
+
|
|
65
|
+
args.genesisStateFile = "genesis.ssz";
|
|
66
|
+
fs.writeFileSync(args.genesisStateFile, state.serialize());
|
|
67
|
+
|
|
68
|
+
// Set logger format to Eph with provided genesisTime
|
|
69
|
+
if (args.logFormatGenesisTime === undefined) args.logFormatGenesisTime = genesisTime;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Note: recycle entire beacon handler
|
|
73
|
+
await beaconHandler(args);
|
|
74
|
+
|
|
75
|
+
if (args.startValidators) {
|
|
76
|
+
// TODO: Map dev option to validator's option
|
|
77
|
+
args.interopIndexes = args.startValidators;
|
|
78
|
+
|
|
79
|
+
// Note: recycle entire validator handler:
|
|
80
|
+
// - keystore handling
|
|
81
|
+
// - metrics
|
|
82
|
+
// - monitoring
|
|
83
|
+
// - keymanager server
|
|
84
|
+
await validatorHandler(args);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {CliCommand, CliCommandOptions} from "@lodestar/utils";
|
|
2
|
+
import {GlobalArgs} from "../../options/index.js";
|
|
3
|
+
import {devHandler} from "./handler.js";
|
|
4
|
+
import {IDevArgs, devOptions} from "./options.js";
|
|
5
|
+
|
|
6
|
+
export const dev: CliCommand<IDevArgs, GlobalArgs> = {
|
|
7
|
+
command: "dev",
|
|
8
|
+
describe: "Quickly bootstrap a beacon node and multiple validators. Use for development and testing",
|
|
9
|
+
docsFolder: "contribution",
|
|
10
|
+
examples: [
|
|
11
|
+
{
|
|
12
|
+
command: "dev --genesisValidators 8 --reset",
|
|
13
|
+
description: "Start a single beacon node with 8 interop validators",
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
options: devOptions as CliCommandOptions<IDevArgs>,
|
|
17
|
+
handler: devHandler,
|
|
18
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {CliCommandOptions, CliOptionDefinition} from "@lodestar/utils";
|
|
2
|
+
import {NetworkName} from "../../networks/index.js";
|
|
3
|
+
import {beaconNodeOptions, globalOptions} from "../../options/index.js";
|
|
4
|
+
import {BeaconArgs, beaconOptions} from "../beacon/options.js";
|
|
5
|
+
import {IValidatorCliArgs, validatorOptions} from "../validator/options.js";
|
|
6
|
+
|
|
7
|
+
type IDevOwnArgs = {
|
|
8
|
+
genesisEth1Hash?: string;
|
|
9
|
+
genesisValidators: number;
|
|
10
|
+
startValidators?: string;
|
|
11
|
+
genesisTime?: number;
|
|
12
|
+
reset?: boolean;
|
|
13
|
+
dumpTestnetFiles?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const devOwnOptions: CliCommandOptions<IDevOwnArgs> = {
|
|
17
|
+
genesisEth1Hash: {
|
|
18
|
+
description: "If present it will create genesis with this eth1 hash.",
|
|
19
|
+
type: "string",
|
|
20
|
+
group: "dev",
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
genesisValidators: {
|
|
24
|
+
alias: ["c"],
|
|
25
|
+
description: "If present it will create genesis with interop validators and start chain.",
|
|
26
|
+
default: 8,
|
|
27
|
+
type: "number",
|
|
28
|
+
group: "dev",
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
startValidators: {
|
|
32
|
+
description: "Start interop validators in inclusive range with notation '0..7'",
|
|
33
|
+
type: "string",
|
|
34
|
+
group: "dev",
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
genesisTime: {
|
|
38
|
+
description: "genesis_time to initialize interop genesis state",
|
|
39
|
+
defaultDescription: "now",
|
|
40
|
+
type: "number",
|
|
41
|
+
group: "dev",
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
reset: {
|
|
45
|
+
description: "To delete chain and validator directories",
|
|
46
|
+
alias: ["r"],
|
|
47
|
+
type: "boolean",
|
|
48
|
+
group: "dev",
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
dumpTestnetFiles: {
|
|
52
|
+
description: "Dump testnet files and exit",
|
|
53
|
+
type: "string",
|
|
54
|
+
group: "dev",
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Add custom defaults different than the ones in `beaconOptions`:
|
|
60
|
+
* - In dev command we don't wanna connect to other peers,
|
|
61
|
+
* - but we do wanna get out of syncing (min peers)
|
|
62
|
+
* - and have api enabled by default (as it's used by validator)
|
|
63
|
+
* Note: use beaconNodeOptions and globalOptions to make sure option key is correct
|
|
64
|
+
*/
|
|
65
|
+
const externalOptionsOverrides: Partial<Record<"network" | keyof typeof beaconNodeOptions, CliOptionDefinition>> = {
|
|
66
|
+
// Custom paths different than regular beacon, validator paths
|
|
67
|
+
// network="dev" will store all data in separate dir than other networks
|
|
68
|
+
network: {
|
|
69
|
+
...globalOptions.network,
|
|
70
|
+
default: "dev" as NetworkName,
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
"sync.isSingleNode": {
|
|
74
|
+
...beaconNodeOptions["sync.isSingleNode"],
|
|
75
|
+
defaultDescription: undefined,
|
|
76
|
+
default: true,
|
|
77
|
+
},
|
|
78
|
+
"network.allowPublishToZeroPeers": {
|
|
79
|
+
...beaconNodeOptions["network.allowPublishToZeroPeers"],
|
|
80
|
+
defaultDescription: undefined,
|
|
81
|
+
default: true,
|
|
82
|
+
},
|
|
83
|
+
eth1: {
|
|
84
|
+
...beaconNodeOptions.eth1,
|
|
85
|
+
defaultDescription: undefined,
|
|
86
|
+
default: false,
|
|
87
|
+
},
|
|
88
|
+
rest: {
|
|
89
|
+
...beaconNodeOptions.rest,
|
|
90
|
+
defaultDescription: undefined,
|
|
91
|
+
default: true,
|
|
92
|
+
},
|
|
93
|
+
"rest.stacktraces": {
|
|
94
|
+
...beaconNodeOptions["rest.stacktraces"],
|
|
95
|
+
default: true,
|
|
96
|
+
},
|
|
97
|
+
"rest.swaggerUI": {
|
|
98
|
+
...beaconNodeOptions["rest.swaggerUI"],
|
|
99
|
+
default: true,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const devOptions = {
|
|
104
|
+
...beaconOptions,
|
|
105
|
+
...validatorOptions,
|
|
106
|
+
...externalOptionsOverrides,
|
|
107
|
+
...devOwnOptions,
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export type IDevArgs = BeaconArgs & IValidatorCliArgs & IDevOwnArgs;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import {CliCommand} from "@lodestar/utils";
|
|
2
|
+
import {GlobalArgs} from "../options/index.js";
|
|
3
|
+
import {beacon} from "./beacon/index.js";
|
|
4
|
+
import {bootnode} from "./bootnode/index.js";
|
|
5
|
+
import {dev} from "./dev/index.js";
|
|
6
|
+
import {lightclient} from "./lightclient/index.js";
|
|
7
|
+
import {validator} from "./validator/index.js";
|
|
8
|
+
|
|
9
|
+
export const cmds: Required<CliCommand<GlobalArgs, Record<never, never>>>["subcommands"] = [
|
|
10
|
+
beacon,
|
|
11
|
+
validator,
|
|
12
|
+
lightclient,
|
|
13
|
+
dev,
|
|
14
|
+
bootnode,
|
|
15
|
+
];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import {getClient} from "@lodestar/api";
|
|
3
|
+
import {Lightclient} from "@lodestar/light-client";
|
|
4
|
+
import {LightClientRestTransport} from "@lodestar/light-client/transport";
|
|
5
|
+
import {getNodeLogger} from "@lodestar/logger/node";
|
|
6
|
+
import {fromHex} from "@lodestar/utils";
|
|
7
|
+
import {getBeaconConfigFromArgs} from "../../config/beaconParams.js";
|
|
8
|
+
import {GlobalArgs} from "../../options/index.js";
|
|
9
|
+
import {getGlobalPaths} from "../../paths/global.js";
|
|
10
|
+
import {parseLoggerArgs} from "../../util/logger.js";
|
|
11
|
+
import {ILightClientArgs} from "./options.js";
|
|
12
|
+
|
|
13
|
+
export async function lightclientHandler(args: ILightClientArgs & GlobalArgs): Promise<void> {
|
|
14
|
+
const {config, network} = getBeaconConfigFromArgs(args);
|
|
15
|
+
const globalPaths = getGlobalPaths(args, network);
|
|
16
|
+
|
|
17
|
+
const logger = getNodeLogger(
|
|
18
|
+
parseLoggerArgs(args, {defaultLogFilepath: path.join(globalPaths.dataDir, "lightclient.log")}, config)
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const api = getClient({baseUrl: args.beaconApiUrl}, {config});
|
|
22
|
+
const {genesisTime, genesisValidatorsRoot} = (await api.beacon.getGenesis()).value();
|
|
23
|
+
|
|
24
|
+
const client = await Lightclient.initializeFromCheckpointRoot({
|
|
25
|
+
config,
|
|
26
|
+
logger,
|
|
27
|
+
genesisData: {
|
|
28
|
+
genesisTime,
|
|
29
|
+
genesisValidatorsRoot,
|
|
30
|
+
},
|
|
31
|
+
checkpointRoot: fromHex(args.checkpointRoot),
|
|
32
|
+
transport: new LightClientRestTransport(api),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
void client.start();
|
|
36
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {CliCommand} from "@lodestar/utils";
|
|
2
|
+
import {GlobalArgs} from "../../options/index.js";
|
|
3
|
+
import {lightclientHandler} from "./handler.js";
|
|
4
|
+
import {ILightClientArgs, lightclientOptions} from "./options.js";
|
|
5
|
+
|
|
6
|
+
export const lightclient: CliCommand<ILightClientArgs, GlobalArgs> = {
|
|
7
|
+
command: "lightclient",
|
|
8
|
+
describe: "Run lightclient",
|
|
9
|
+
docsFolder: "libraries/lightclient-prover",
|
|
10
|
+
examples: [
|
|
11
|
+
{
|
|
12
|
+
command: "lightclient --network hoodi",
|
|
13
|
+
description: "Run lightclient with hoodi network",
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
options: lightclientOptions,
|
|
17
|
+
handler: lightclientHandler,
|
|
18
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {CliCommandOptions} from "@lodestar/utils";
|
|
2
|
+
import {LogArgs, logOptions} from "../../options/logOptions.js";
|
|
3
|
+
|
|
4
|
+
export type ILightClientArgs = LogArgs & {
|
|
5
|
+
beaconApiUrl: string;
|
|
6
|
+
checkpointRoot: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const lightclientOptions: CliCommandOptions<ILightClientArgs> = {
|
|
10
|
+
...logOptions,
|
|
11
|
+
beaconApiUrl: {
|
|
12
|
+
description: "Url to a beacon node that support lightclient API",
|
|
13
|
+
type: "string",
|
|
14
|
+
demandOption: true,
|
|
15
|
+
},
|
|
16
|
+
checkpointRoot: {
|
|
17
|
+
description: "Checkpoint root hex string to sync the lightclient from, start with 0x",
|
|
18
|
+
type: "string",
|
|
19
|
+
demandOption: true,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {SecretKey} from "@chainsafe/blst";
|
|
2
|
+
import {getClient} from "@lodestar/api";
|
|
3
|
+
import {createBeaconConfig} from "@lodestar/config";
|
|
4
|
+
import {DOMAIN_BLS_TO_EXECUTION_CHANGE, ForkName} from "@lodestar/params";
|
|
5
|
+
import {computeSigningRoot} from "@lodestar/state-transition";
|
|
6
|
+
import {capella, ssz} from "@lodestar/types";
|
|
7
|
+
import {CliCommand, fromHex} from "@lodestar/utils";
|
|
8
|
+
import {getBeaconConfigFromArgs} from "../../config/index.js";
|
|
9
|
+
import {GlobalArgs} from "../../options/index.js";
|
|
10
|
+
import {IValidatorCliArgs} from "./options.js";
|
|
11
|
+
|
|
12
|
+
type BlsToExecutionChangeArgs = {
|
|
13
|
+
publicKey: string;
|
|
14
|
+
fromBlsPrivkey: string;
|
|
15
|
+
toExecutionAddress: string;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const blsToExecutionChange: CliCommand<BlsToExecutionChangeArgs, IValidatorCliArgs & GlobalArgs> = {
|
|
19
|
+
command: "bls-to-execution-change",
|
|
20
|
+
|
|
21
|
+
describe:
|
|
22
|
+
"Performs BLS To Execution Change for a given validator (as identified via `publicKey`. \
|
|
23
|
+
If no `publicKey` is provided, a prompt will ask the user which validator they would \
|
|
24
|
+
like to choose for BLS To Execution Change.",
|
|
25
|
+
|
|
26
|
+
examples: [
|
|
27
|
+
{
|
|
28
|
+
command: "validator bls-to-execution-change --publicKey 0xF00 --fromBlsPrivkey ... --toExecutionAddress ...",
|
|
29
|
+
description: "Perform BLS To Execution Change for the validator who has a public key 0xF00",
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
|
|
33
|
+
options: {
|
|
34
|
+
publicKey: {
|
|
35
|
+
description: "Validator public key for which to set withdrawal address hence enabling withdrawals",
|
|
36
|
+
type: "string",
|
|
37
|
+
demandOption: true,
|
|
38
|
+
},
|
|
39
|
+
fromBlsPrivkey: {
|
|
40
|
+
description: "Bls withdrawals private key to sign the message",
|
|
41
|
+
type: "string",
|
|
42
|
+
demandOption: true,
|
|
43
|
+
},
|
|
44
|
+
toExecutionAddress: {
|
|
45
|
+
description: "Address to which the validator's balances will be set to be withdrawn.",
|
|
46
|
+
type: "string",
|
|
47
|
+
demandOption: true,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
|
|
51
|
+
handler: async (args) => {
|
|
52
|
+
const {publicKey} = args;
|
|
53
|
+
// Fetch genesisValidatorsRoot always from beacon node as anyway beacon node is needed for
|
|
54
|
+
// submitting the signed message
|
|
55
|
+
const {config: chainForkConfig} = getBeaconConfigFromArgs(args);
|
|
56
|
+
const client = getClient({urls: args.beaconNodes}, {config: chainForkConfig});
|
|
57
|
+
const {genesisValidatorsRoot} = (await client.beacon.getGenesis()).value();
|
|
58
|
+
const config = createBeaconConfig(chainForkConfig, genesisValidatorsRoot);
|
|
59
|
+
|
|
60
|
+
const validators = (await client.beacon.postStateValidators({stateId: "head", validatorIds: [publicKey]})).value();
|
|
61
|
+
const validator = validators[0];
|
|
62
|
+
if (validator === undefined) {
|
|
63
|
+
throw new Error(`Validator pubkey ${publicKey} not found in state`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const blsPrivkey = SecretKey.fromBytes(fromHex(args.fromBlsPrivkey));
|
|
67
|
+
const fromBlsPubkey = blsPrivkey.toPublicKey().toBytes();
|
|
68
|
+
|
|
69
|
+
const blsToExecutionChange: capella.BLSToExecutionChange = {
|
|
70
|
+
validatorIndex: validator.index,
|
|
71
|
+
fromBlsPubkey,
|
|
72
|
+
toExecutionAddress: fromHex(args.toExecutionAddress),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const signatureFork = ForkName.phase0;
|
|
76
|
+
const domain = config.getDomainAtFork(signatureFork, DOMAIN_BLS_TO_EXECUTION_CHANGE);
|
|
77
|
+
const signingRoot = computeSigningRoot(ssz.capella.BLSToExecutionChange, blsToExecutionChange, domain);
|
|
78
|
+
const signedBLSToExecutionChange = {
|
|
79
|
+
message: blsToExecutionChange,
|
|
80
|
+
signature: blsPrivkey.sign(signingRoot).toBytes(),
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
(
|
|
84
|
+
await client.beacon.submitPoolBLSToExecutionChange({
|
|
85
|
+
blsToExecutionChanges: [signedBLSToExecutionChange],
|
|
86
|
+
})
|
|
87
|
+
).assertOk();
|
|
88
|
+
|
|
89
|
+
console.log(`Submitted bls to execution change for ${publicKey}`);
|
|
90
|
+
},
|
|
91
|
+
};
|