-
-
Notifications
You must be signed in to change notification settings - Fork 471
Expand file tree
/
Copy pathvoluntaryExitFromApi.test.ts
More file actions
95 lines (84 loc) · 3.57 KB
/
Copy pathvoluntaryExitFromApi.test.ts
File metadata and controls
95 lines (84 loc) · 3.57 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
import path from "node:path";
import {describe, it, vi, expect, afterAll, beforeEach, afterEach} from "vitest";
import {ApiError, getClient} from "@lodestar/api";
import {getClient as getKeymanagerClient} from "@lodestar/api/keymanager";
import {config} from "@lodestar/config/default";
import {interopSecretKey} from "@lodestar/state-transition";
import {spawnCliCommand} from "@lodestar/test-utils";
import {retry} from "@lodestar/utils";
import {testFilesDir} from "../utils.js";
describe("voluntary exit from api", function () {
vi.setConfig({testTimeout: 60_000});
it("Perform a voluntary exit", async () => {
// Start dev node with keymanager
const keymanagerPort = 38012;
const beaconPort = 39012;
const devProc = await spawnCliCommand(
"packages/cli/bin/lodestar.js",
[
// ⏎
"dev",
`--dataDir=${path.join(testFilesDir, "voluntary-exit-api-test")}`,
"--genesisValidators=8",
"--startValidators=0..7",
"--rest",
`--rest.port=${beaconPort}`,
`--beaconNodes=http://127.0.0.1:${beaconPort}`,
// Speed up test to make genesis happen faster
"--params.SECONDS_PER_SLOT=2",
// Allow voluntary exists to be valid immediately
"--params.SHARD_COMMITTEE_PERIOD=0",
// Enable keymanager API
"--keymanager",
`--keymanager.port=${keymanagerPort}`,
// Disable bearer token auth to simplify testing
"--keymanager.authEnabled=false",
],
{pipeStdioToParent: false, logPrefix: "dev", testContext: {beforeEach, afterEach, afterAll}}
);
// Exit early if process exits
devProc.on("exit", (code) => {
if (code !== null && code > 0) {
throw new Error(`devProc process exited with code ${code}`);
}
});
const beaconClient = getClient({baseUrl: `http://127.0.0.1:${beaconPort}`}, {config}).beacon;
const keymanagerClient = getKeymanagerClient({baseUrl: `http://127.0.0.1:${keymanagerPort}`}, {config});
// Wait for beacon node API to be available + genesis
await retry(
async () => {
const head = await beaconClient.getBlockHeader("head");
ApiError.assert(head);
if (head.response.data.header.message.slot < 1) throw Error("pre-genesis");
},
{retryDelay: 1000, retries: 20}
);
// 1. create signed voluntary exit message from keymanager
const exitEpoch = 0;
const indexToExit = 0;
const pubkeyToExit = interopSecretKey(indexToExit).toPublicKey().toHex();
const res = await keymanagerClient.signVoluntaryExit(pubkeyToExit, exitEpoch);
ApiError.assert(res);
const signedVoluntaryExit = res.response.data;
expect(signedVoluntaryExit.message.epoch).toBe(exitEpoch);
expect(signedVoluntaryExit.message.validatorIndex).toBe(indexToExit);
// Signature will be verified when submitting to beacon node
expect(signedVoluntaryExit.signature).toBeDefined();
// 2. submit signed voluntary exit message to beacon node
ApiError.assert(await beaconClient.submitPoolVoluntaryExit(signedVoluntaryExit));
// 3. confirm validator status is 'active_exiting'
await retry(
async () => {
const res = await beaconClient.getStateValidator("head", pubkeyToExit);
ApiError.assert(res);
if (res.response.data.status !== "active_exiting") {
throw Error("Validator not exiting");
} else {
// eslint-disable-next-line no-console
console.log(`Confirmed validator ${pubkeyToExit} = ${res.response.data.status}`);
}
},
{retryDelay: 1000, retries: 20}
);
});
});