@chainsafe/lodestar 1.42.0-dev.8961934298 → 1.42.0-dev.8b81ee6c3e
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/lib/cmds/validator/voluntaryExit.d.ts +1 -0
- package/lib/cmds/validator/voluntaryExit.d.ts.map +1 -1
- package/lib/cmds/validator/voluntaryExit.js +50 -9
- package/lib/cmds/validator/voluntaryExit.js.map +1 -1
- package/package.json +14 -14
- package/src/cmds/validator/voluntaryExit.ts +63 -11
package/.git-data.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voluntaryExit.d.ts","sourceRoot":"","sources":["../../../src/cmds/validator/voluntaryExit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"voluntaryExit.d.ts","sourceRoot":"","sources":["../../../src/cmds/validator/voluntaryExit.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,UAAU,EAAuB,MAAM,iBAAiB,CAAC;AAGjE,OAAO,EAAC,UAAU,EAAC,MAAM,wBAAwB,CAAC;AAElD,OAAO,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAG/C,KAAK,iBAAiB,GAAG;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,UAAU,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,UAAU,CAiKvF,CAAC"}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
1
3
|
import inquirer from "inquirer";
|
|
2
4
|
import { Signature } from "@chainsafe/blst";
|
|
3
5
|
import { getClient } from "@lodestar/api";
|
|
@@ -7,7 +9,7 @@ import { ssz } from "@lodestar/types";
|
|
|
7
9
|
import { fromHex, toPubkeyHex } from "@lodestar/utils";
|
|
8
10
|
import { SignableMessageType, SignerType, externalSignerPostSignature } from "@lodestar/validator";
|
|
9
11
|
import { getBeaconConfigFromArgs } from "../../config/index.js";
|
|
10
|
-
import { YargsError, ensure0xPrefix, wrapError } from "../../util/index.js";
|
|
12
|
+
import { YargsError, ensure0xPrefix, wrapError, writeFile600Perm } from "../../util/index.js";
|
|
11
13
|
import { getSignersFromArgs } from "./signers/index.js";
|
|
12
14
|
export const voluntaryExit = {
|
|
13
15
|
command: "voluntary-exit",
|
|
@@ -42,6 +44,10 @@ If no `pubkeys` are provided, it will exit all validators that have been importe
|
|
|
42
44
|
description: "Skip confirmation prompt",
|
|
43
45
|
type: "boolean",
|
|
44
46
|
},
|
|
47
|
+
saveExitsPath: {
|
|
48
|
+
description: "Write signed voluntary exit messages to a folder instead of publishing to the beacon node",
|
|
49
|
+
type: "string",
|
|
50
|
+
},
|
|
45
51
|
},
|
|
46
52
|
handler: async (args) => {
|
|
47
53
|
// Fetch genesisValidatorsRoot always from beacon node
|
|
@@ -66,7 +72,7 @@ If no `pubkeys` are provided, it will exit all validators that have been importe
|
|
|
66
72
|
}
|
|
67
73
|
const signersToExit = selectSignersToExit(args, signers);
|
|
68
74
|
const validatorsToExit = await resolveValidatorIndexes(client, signersToExit);
|
|
69
|
-
if (!args.yes) {
|
|
75
|
+
if (!args.yes && !args.saveExitsPath) {
|
|
70
76
|
console.log("\nWARNING: THIS IS AN IRREVERSIBLE OPERATION\n");
|
|
71
77
|
const confirmation = await inquirer.prompt([
|
|
72
78
|
{
|
|
@@ -81,19 +87,30 @@ ${validatorsToExit.map((v) => `${v.pubkey} ${v.index} ${v.status}`).join("\n")}`
|
|
|
81
87
|
throw new YargsError("not confirmed");
|
|
82
88
|
}
|
|
83
89
|
}
|
|
90
|
+
const signedExits = [];
|
|
84
91
|
const alreadySubmitted = [];
|
|
85
92
|
for (const [i, validatorToExit] of validatorsToExit.entries()) {
|
|
86
|
-
const
|
|
93
|
+
const res = await wrapError(createSignedVoluntaryExit({ config }, exitEpoch, validatorToExit));
|
|
87
94
|
const { pubkey, index } = validatorToExit;
|
|
88
|
-
if (err
|
|
89
|
-
console.log(`
|
|
95
|
+
if (res.err !== null) {
|
|
96
|
+
console.log(`Signing errored for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}: ${res.err.message}`);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const signedExit = res.result;
|
|
100
|
+
if (args.saveExitsPath) {
|
|
101
|
+
signedExits.push({ exit: signedExit, index, pubkey });
|
|
102
|
+
console.log(`Signed voluntary exit for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}`);
|
|
90
103
|
}
|
|
91
104
|
else {
|
|
92
|
-
|
|
105
|
+
const submitRes = await wrapError(client.beacon.submitPoolVoluntaryExit({ signedVoluntaryExit: signedExit }).then((r) => r.assertOk()));
|
|
106
|
+
if (submitRes.err === null) {
|
|
107
|
+
console.log(`Submitted voluntary exit for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}`);
|
|
108
|
+
}
|
|
109
|
+
else if (submitRes.err.message.includes("ALREADY_EXISTS")) {
|
|
93
110
|
alreadySubmitted.push(validatorToExit);
|
|
94
111
|
}
|
|
95
112
|
else {
|
|
96
|
-
console.log(`Voluntary exit errored for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}: ${err.message}`);
|
|
113
|
+
console.log(`Voluntary exit errored for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}: ${submitRes.err.message}`);
|
|
97
114
|
}
|
|
98
115
|
}
|
|
99
116
|
}
|
|
@@ -104,9 +121,33 @@ ${validatorsToExit.map((v) => `${v.pubkey} ${v.index} ${v.status}`).join("\n")}`
|
|
|
104
121
|
console.log(` - ${pubkey} (${index})`);
|
|
105
122
|
}
|
|
106
123
|
}
|
|
124
|
+
if (args.saveExitsPath && signedExits.length > 0) {
|
|
125
|
+
try {
|
|
126
|
+
fs.mkdirSync(args.saveExitsPath, { recursive: true });
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
throw new YargsError(`Failed to create a directory "${args.saveExitsPath}": ${e.message}`);
|
|
130
|
+
}
|
|
131
|
+
const failedToSave = [];
|
|
132
|
+
for (const { exit, index, pubkey } of signedExits) {
|
|
133
|
+
const filename = path.join(args.saveExitsPath, `validator_${index}_exit.json`);
|
|
134
|
+
try {
|
|
135
|
+
const json = JSON.stringify(ssz.phase0.SignedVoluntaryExit.toJson(exit), null, 2);
|
|
136
|
+
writeFile600Perm(filename, json);
|
|
137
|
+
console.log(`Saved signed voluntary exit for ${pubkey} (${index}) to ${filename}`);
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
failedToSave.push({ index, pubkey });
|
|
141
|
+
console.error(`Failed to save the signed exit of ${pubkey} (${index}) to ${filename}: ${e.message}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (failedToSave.length > 0) {
|
|
145
|
+
throw new YargsError(`Failed to save ${failedToSave.length}/${signedExits.length} signed voluntary exits`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
107
148
|
},
|
|
108
149
|
};
|
|
109
|
-
async function
|
|
150
|
+
async function createSignedVoluntaryExit({ config }, exitEpoch, validatorToExit) {
|
|
110
151
|
const { index, signer, pubkey } = validatorToExit;
|
|
111
152
|
const slot = computeStartSlotAtEpoch(exitEpoch);
|
|
112
153
|
const domain = config.getDomainForVoluntaryExit(slot);
|
|
@@ -132,7 +173,7 @@ async function processVoluntaryExit({ config, client }, exitEpoch, validatorToEx
|
|
|
132
173
|
message: voluntaryExit,
|
|
133
174
|
signature: signature.toBytes(),
|
|
134
175
|
};
|
|
135
|
-
|
|
176
|
+
return signedVoluntaryExit;
|
|
136
177
|
}
|
|
137
178
|
function selectSignersToExit(args, signers) {
|
|
138
179
|
const signersWithPubkey = signers.map((signer) => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"voluntaryExit.js","sourceRoot":"","sources":["../../../src/cmds/validator/voluntaryExit.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAY,SAAS,EAAC,MAAM,eAAe,CAAC;AACnD,OAAO,EAAe,kBAAkB,EAAC,MAAM,kBAAkB,CAAC;AAClE,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAgC,GAAG,EAAC,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAa,OAAO,EAAE,WAAW,EAAC,MAAM,iBAAiB,CAAC;AACjE,OAAO,EAAC,mBAAmB,EAAU,UAAU,EAAE,2BAA2B,EAAC,MAAM,qBAAqB,CAAC;AACzG,OAAO,EAAC,uBAAuB,EAAC,MAAM,uBAAuB,CAAC;AAE9D,OAAO,EAAC,UAAU,EAAE,cAAc,EAAE,SAAS,EAAC,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"voluntaryExit.js","sourceRoot":"","sources":["../../../src/cmds/validator/voluntaryExit.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chainsafe/lodestar",
|
|
3
|
-
"version": "1.42.0-dev.
|
|
3
|
+
"version": "1.42.0-dev.8b81ee6c3e",
|
|
4
4
|
"description": "Command line interface for lodestar",
|
|
5
5
|
"author": "ChainSafe Systems",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -69,17 +69,17 @@
|
|
|
69
69
|
"@libp2p/crypto": "^5.1.13",
|
|
70
70
|
"@libp2p/interface": "^3.1.0",
|
|
71
71
|
"@libp2p/peer-id": "^6.0.4",
|
|
72
|
-
"@lodestar/api": "^1.42.0-dev.
|
|
73
|
-
"@lodestar/beacon-node": "^1.42.0-dev.
|
|
74
|
-
"@lodestar/config": "^1.42.0-dev.
|
|
75
|
-
"@lodestar/db": "^1.42.0-dev.
|
|
76
|
-
"@lodestar/light-client": "^1.42.0-dev.
|
|
77
|
-
"@lodestar/logger": "^1.42.0-dev.
|
|
78
|
-
"@lodestar/params": "^1.42.0-dev.
|
|
79
|
-
"@lodestar/state-transition": "^1.42.0-dev.
|
|
80
|
-
"@lodestar/types": "^1.42.0-dev.
|
|
81
|
-
"@lodestar/utils": "^1.42.0-dev.
|
|
82
|
-
"@lodestar/validator": "^1.42.0-dev.
|
|
72
|
+
"@lodestar/api": "^1.42.0-dev.8b81ee6c3e",
|
|
73
|
+
"@lodestar/beacon-node": "^1.42.0-dev.8b81ee6c3e",
|
|
74
|
+
"@lodestar/config": "^1.42.0-dev.8b81ee6c3e",
|
|
75
|
+
"@lodestar/db": "^1.42.0-dev.8b81ee6c3e",
|
|
76
|
+
"@lodestar/light-client": "^1.42.0-dev.8b81ee6c3e",
|
|
77
|
+
"@lodestar/logger": "^1.42.0-dev.8b81ee6c3e",
|
|
78
|
+
"@lodestar/params": "^1.42.0-dev.8b81ee6c3e",
|
|
79
|
+
"@lodestar/state-transition": "^1.42.0-dev.8b81ee6c3e",
|
|
80
|
+
"@lodestar/types": "^1.42.0-dev.8b81ee6c3e",
|
|
81
|
+
"@lodestar/utils": "^1.42.0-dev.8b81ee6c3e",
|
|
82
|
+
"@lodestar/validator": "^1.42.0-dev.8b81ee6c3e",
|
|
83
83
|
"@multiformats/multiaddr": "^13.0.1",
|
|
84
84
|
"deepmerge": "^4.3.1",
|
|
85
85
|
"ethers": "^6.7.0",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
"devDependencies": {
|
|
97
97
|
"@chainsafe/as-sha256": "^1.2.0",
|
|
98
98
|
"@ethereumjs/rlp": "^4.0.1",
|
|
99
|
-
"@lodestar/test-utils": "^1.42.0-dev.
|
|
99
|
+
"@lodestar/test-utils": "^1.42.0-dev.8b81ee6c3e",
|
|
100
100
|
"@types/debug": "^4.1.7",
|
|
101
101
|
"@types/inquirer": "^9.0.3",
|
|
102
102
|
"@types/js-yaml": "^4.0.5",
|
|
@@ -109,5 +109,5 @@
|
|
|
109
109
|
"web3": "^4.0.3",
|
|
110
110
|
"web3-eth-accounts": "^4.0.3"
|
|
111
111
|
},
|
|
112
|
-
"gitHead": "
|
|
112
|
+
"gitHead": "85501e0588b8f1e387d777777effb259c9534bd4"
|
|
113
113
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
1
3
|
import inquirer from "inquirer";
|
|
2
4
|
import {Signature} from "@chainsafe/blst";
|
|
3
5
|
import {ApiClient, getClient} from "@lodestar/api";
|
|
@@ -13,7 +15,7 @@ import {CliCommand, fromHex, toPubkeyHex} from "@lodestar/utils";
|
|
|
13
15
|
import {SignableMessageType, Signer, SignerType, externalSignerPostSignature} from "@lodestar/validator";
|
|
14
16
|
import {getBeaconConfigFromArgs} from "../../config/index.js";
|
|
15
17
|
import {GlobalArgs} from "../../options/index.js";
|
|
16
|
-
import {YargsError, ensure0xPrefix, wrapError} from "../../util/index.js";
|
|
18
|
+
import {YargsError, ensure0xPrefix, wrapError, writeFile600Perm} from "../../util/index.js";
|
|
17
19
|
import {IValidatorCliArgs} from "./options.js";
|
|
18
20
|
import {getSignersFromArgs} from "./signers/index.js";
|
|
19
21
|
|
|
@@ -21,6 +23,7 @@ type VoluntaryExitArgs = {
|
|
|
21
23
|
exitEpoch?: number;
|
|
22
24
|
pubkeys?: string[];
|
|
23
25
|
yes?: boolean;
|
|
26
|
+
saveExitsPath?: string;
|
|
24
27
|
};
|
|
25
28
|
|
|
26
29
|
export const voluntaryExit: CliCommand<VoluntaryExitArgs, IValidatorCliArgs & GlobalArgs> = {
|
|
@@ -65,6 +68,11 @@ If no `pubkeys` are provided, it will exit all validators that have been importe
|
|
|
65
68
|
description: "Skip confirmation prompt",
|
|
66
69
|
type: "boolean",
|
|
67
70
|
},
|
|
71
|
+
|
|
72
|
+
saveExitsPath: {
|
|
73
|
+
description: "Write signed voluntary exit messages to a folder instead of publishing to the beacon node",
|
|
74
|
+
type: "string",
|
|
75
|
+
},
|
|
68
76
|
},
|
|
69
77
|
|
|
70
78
|
handler: async (args) => {
|
|
@@ -94,7 +102,7 @@ If no `pubkeys` are provided, it will exit all validators that have been importe
|
|
|
94
102
|
const signersToExit = selectSignersToExit(args, signers);
|
|
95
103
|
const validatorsToExit = await resolveValidatorIndexes(client, signersToExit);
|
|
96
104
|
|
|
97
|
-
if (!args.yes) {
|
|
105
|
+
if (!args.yes && !args.saveExitsPath) {
|
|
98
106
|
console.log("\nWARNING: THIS IS AN IRREVERSIBLE OPERATION\n");
|
|
99
107
|
const confirmation = await inquirer.prompt<{yes: boolean}>([
|
|
100
108
|
{
|
|
@@ -110,18 +118,34 @@ ${validatorsToExit.map((v) => `${v.pubkey} ${v.index} ${v.status}`).join("\n")}`
|
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
|
|
121
|
+
const signedExits: {exit: phase0.SignedVoluntaryExit; index: ValidatorIndex; pubkey: string}[] = [];
|
|
113
122
|
const alreadySubmitted = [];
|
|
123
|
+
|
|
114
124
|
for (const [i, validatorToExit] of validatorsToExit.entries()) {
|
|
115
|
-
const
|
|
125
|
+
const res = await wrapError(createSignedVoluntaryExit({config}, exitEpoch, validatorToExit));
|
|
116
126
|
const {pubkey, index} = validatorToExit;
|
|
117
|
-
|
|
118
|
-
|
|
127
|
+
|
|
128
|
+
if (res.err !== null) {
|
|
129
|
+
console.log(`Signing errored for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}: ${res.err.message}`);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const signedExit = res.result;
|
|
134
|
+
|
|
135
|
+
if (args.saveExitsPath) {
|
|
136
|
+
signedExits.push({exit: signedExit, index, pubkey});
|
|
137
|
+
console.log(`Signed voluntary exit for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}`);
|
|
119
138
|
} else {
|
|
120
|
-
|
|
139
|
+
const submitRes = await wrapError(
|
|
140
|
+
client.beacon.submitPoolVoluntaryExit({signedVoluntaryExit: signedExit}).then((r) => r.assertOk())
|
|
141
|
+
);
|
|
142
|
+
if (submitRes.err === null) {
|
|
143
|
+
console.log(`Submitted voluntary exit for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}`);
|
|
144
|
+
} else if (submitRes.err.message.includes("ALREADY_EXISTS")) {
|
|
121
145
|
alreadySubmitted.push(validatorToExit);
|
|
122
146
|
} else {
|
|
123
147
|
console.log(
|
|
124
|
-
`Voluntary exit errored for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}: ${err.message}`
|
|
148
|
+
`Voluntary exit errored for ${pubkey} (${index}) ${i + 1}/${signersToExit.length}: ${submitRes.err.message}`
|
|
125
149
|
);
|
|
126
150
|
}
|
|
127
151
|
}
|
|
@@ -134,14 +158,42 @@ ${validatorsToExit.map((v) => `${v.pubkey} ${v.index} ${v.status}`).join("\n")}`
|
|
|
134
158
|
console.log(` - ${pubkey} (${index})`);
|
|
135
159
|
}
|
|
136
160
|
}
|
|
161
|
+
|
|
162
|
+
if (args.saveExitsPath && signedExits.length > 0) {
|
|
163
|
+
try {
|
|
164
|
+
fs.mkdirSync(args.saveExitsPath, {recursive: true});
|
|
165
|
+
} catch (e) {
|
|
166
|
+
throw new YargsError(`Failed to create a directory "${args.saveExitsPath}": ${(e as Error).message}`);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const failedToSave: {index: ValidatorIndex; pubkey: string}[] = [];
|
|
170
|
+
|
|
171
|
+
for (const {exit, index, pubkey} of signedExits) {
|
|
172
|
+
const filename = path.join(args.saveExitsPath, `validator_${index}_exit.json`);
|
|
173
|
+
try {
|
|
174
|
+
const json = JSON.stringify(ssz.phase0.SignedVoluntaryExit.toJson(exit), null, 2);
|
|
175
|
+
writeFile600Perm(filename, json);
|
|
176
|
+
console.log(`Saved signed voluntary exit for ${pubkey} (${index}) to ${filename}`);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
failedToSave.push({index, pubkey});
|
|
179
|
+
console.error(
|
|
180
|
+
`Failed to save the signed exit of ${pubkey} (${index}) to ${filename}: ${(e as Error).message}`
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (failedToSave.length > 0) {
|
|
186
|
+
throw new YargsError(`Failed to save ${failedToSave.length}/${signedExits.length} signed voluntary exits`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
137
189
|
},
|
|
138
190
|
};
|
|
139
191
|
|
|
140
|
-
async function
|
|
141
|
-
{config
|
|
192
|
+
async function createSignedVoluntaryExit(
|
|
193
|
+
{config}: {config: BeaconConfig},
|
|
142
194
|
exitEpoch: Epoch,
|
|
143
195
|
validatorToExit: {index: ValidatorIndex; signer: Signer; pubkey: string}
|
|
144
|
-
): Promise<
|
|
196
|
+
): Promise<phase0.SignedVoluntaryExit> {
|
|
145
197
|
const {index, signer, pubkey} = validatorToExit;
|
|
146
198
|
const slot = computeStartSlotAtEpoch(exitEpoch);
|
|
147
199
|
const domain = config.getDomainForVoluntaryExit(slot);
|
|
@@ -170,7 +222,7 @@ async function processVoluntaryExit(
|
|
|
170
222
|
signature: signature.toBytes(),
|
|
171
223
|
};
|
|
172
224
|
|
|
173
|
-
|
|
225
|
+
return signedVoluntaryExit;
|
|
174
226
|
}
|
|
175
227
|
|
|
176
228
|
type SignerPubkey = {signer: Signer; pubkey: string};
|