-
-
Notifications
You must be signed in to change notification settings - Fork 439
Expand file tree
/
Copy pathblsToExecutionChange.ts
More file actions
91 lines (79 loc) · 3.46 KB
/
blsToExecutionChange.ts
File metadata and controls
91 lines (79 loc) · 3.46 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
import {SecretKey} from "@chainsafe/lodestar-z/blst";
import {getClient} from "@lodestar/api";
import {createBeaconConfig} from "@lodestar/config";
import {DOMAIN_BLS_TO_EXECUTION_CHANGE, ForkName} from "@lodestar/params";
import {computeSigningRoot} from "@lodestar/state-transition";
import {capella, ssz} from "@lodestar/types";
import {CliCommand, fromHex} from "@lodestar/utils";
import {getBeaconConfigFromArgs} from "../../config/index.js";
import {GlobalArgs} from "../../options/index.js";
import {IValidatorCliArgs} from "./options.js";
type BlsToExecutionChangeArgs = {
publicKey: string;
fromBlsPrivkey: string;
toExecutionAddress: string;
};
export const blsToExecutionChange: CliCommand<BlsToExecutionChangeArgs, IValidatorCliArgs & GlobalArgs> = {
command: "bls-to-execution-change",
describe:
"Performs BLS To Execution Change for a given validator (as identified via `publicKey`. \
If no `publicKey` is provided, a prompt will ask the user which validator they would \
like to choose for BLS To Execution Change.",
examples: [
{
command: "validator bls-to-execution-change --publicKey 0xF00 --fromBlsPrivkey ... --toExecutionAddress ...",
description: "Perform BLS To Execution Change for the validator who has a public key 0xF00",
},
],
options: {
publicKey: {
description: "Validator public key for which to set withdrawal address hence enabling withdrawals",
type: "string",
demandOption: true,
},
fromBlsPrivkey: {
description: "Bls withdrawals private key to sign the message",
type: "string",
demandOption: true,
},
toExecutionAddress: {
description: "Address to which the validator's balances will be set to be withdrawn.",
type: "string",
demandOption: true,
},
},
handler: async (args) => {
const {publicKey} = args;
// Fetch genesisValidatorsRoot always from beacon node as anyway beacon node is needed for
// submitting the signed message
const {config: chainForkConfig} = getBeaconConfigFromArgs(args);
const client = getClient({urls: args.beaconNodes}, {config: chainForkConfig});
const {genesisValidatorsRoot} = (await client.beacon.getGenesis()).value();
const config = createBeaconConfig(chainForkConfig, genesisValidatorsRoot);
const validators = (await client.beacon.postStateValidators({stateId: "head", validatorIds: [publicKey]})).value();
const validator = validators[0];
if (validator === undefined) {
throw new Error(`Validator pubkey ${publicKey} not found in state`);
}
const blsPrivkey = SecretKey.fromBytes(fromHex(args.fromBlsPrivkey));
const fromBlsPubkey = blsPrivkey.toPublicKey().toBytes();
const blsToExecutionChange: capella.BLSToExecutionChange = {
validatorIndex: validator.index,
fromBlsPubkey,
toExecutionAddress: fromHex(args.toExecutionAddress),
};
const signatureFork = ForkName.phase0;
const domain = config.getDomainAtFork(signatureFork, DOMAIN_BLS_TO_EXECUTION_CHANGE);
const signingRoot = computeSigningRoot(ssz.capella.BLSToExecutionChange, blsToExecutionChange, domain);
const signedBLSToExecutionChange = {
message: blsToExecutionChange,
signature: blsPrivkey.sign(signingRoot).toBytes(),
};
(
await client.beacon.submitPoolBLSToExecutionChange({
blsToExecutionChanges: [signedBLSToExecutionChange],
})
).assertOk();
console.log(`Submitted bls to execution change for ${publicKey}`);
},
};