-
-
Notifications
You must be signed in to change notification settings - Fork 267
/
externalSigner.ts
80 lines (69 loc) 路 2.59 KB
/
externalSigner.ts
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
import fs from "node:fs";
import path from "node:path";
import {dirSync as tmpDirSync} from "tmp";
import {GenericContainer, Wait, StartedTestContainer} from "testcontainers";
import {ForkSeq} from "@lodestar/params";
const web3signerVersion = "23.11.0";
/** Till what version is the web3signer image updated for signature verification */
const supportedForkSeq = ForkSeq.capella;
export type StartedExternalSigner = {
container: StartedTestContainer;
url: string;
supportedForkSeq: ForkSeq;
};
export async function startExternalSigner({
keystoreStrings,
password,
}: {
keystoreStrings: string[];
password: string;
}): Promise<StartedExternalSigner> {
// path to store configuration
const tmpDir = tmpDirSync({
unsafeCleanup: true,
// In Github runner NodeJS process probably runs as root, so web3signer doesn't have permissions to read config dir
mode: 755,
});
// Apply permissions again to hopefully make Github runner happy >.<
fs.chmodSync(tmpDir.name, 0o755);
const configDirPathHost = tmpDir.name;
const configDirPathContainer = "/var/web3signer/config";
// keystore content and file paths
const passwordFilename = "password.txt";
for (const [idx, keystoreString] of keystoreStrings.entries()) {
fs.writeFileSync(path.join(configDirPathHost, `keystore-${idx}.json`), keystoreString);
}
fs.writeFileSync(path.join(configDirPathHost, passwordFilename), password);
const port = 9000;
const startedContainer = await new GenericContainer(`consensys/web3signer:${web3signerVersion}`)
.withHealthCheck({
test: ["CMD-SHELL", `curl -f http://localhost:${port}/healthcheck || exit 1`],
interval: 1000,
timeout: 3000,
retries: 5,
startPeriod: 1000,
})
.withWaitStrategy(Wait.forHealthCheck())
.withExposedPorts(port)
.withBindMounts([{source: configDirPathHost, target: configDirPathContainer, mode: "ro"}])
.withCommand([
"eth2",
`--keystores-path=${configDirPathContainer}`,
// Don't use path.join here, the container is running on unix filesystem
`--keystores-password-file=${configDirPathContainer}/${passwordFilename}`,
"--slashing-protection-enabled=false",
])
.start();
const url = `http://localhost:${startedContainer.getMappedPort(port)}`;
const stream = await startedContainer.logs();
stream
.on("data", (line) => process.stdout.write(line))
.on("err", (line) => process.stderr.write(line))
// eslint-disable-next-line no-console
.on("end", () => console.log("Stream closed"));
return {
container: startedContainer,
url: url,
supportedForkSeq,
};
}