Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use mix of local key manager and external signer for sim tests #4583

Merged
merged 11 commits into from
Sep 23, 2022
10 changes: 1 addition & 9 deletions packages/cli/test/simulation/simulation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,28 @@ const forksCases: {
params: {
altairEpoch: number;
bellatrixEpoch: number;
withExternalSigner?: boolean;
runTill: Epoch;
};
}[] = [
{
title: "mixed forks",
params: {altairEpoch: 2, bellatrixEpoch: 4, runTill: 6},
},
// {
// title: "mixed forks with remote signer",
// params: {altairEpoch: 1, bellatrixEpoch: 2, withExternalSigner: true, runTill: 3},
// },
];

let testCases = 0;

for (const {beaconNodes, validatorClients, validatorsPerClient} of nodeCases) {
for (const {
title,
params: {altairEpoch, bellatrixEpoch, withExternalSigner, runTill},
params: {altairEpoch, bellatrixEpoch, runTill},
} of forksCases) {
const testIdStr = [
`beaconNodes-${beaconNodes}`,
`validatorClients-${validatorClients}`,
`validatorsPerClient-${validatorsPerClient}`,
`altair-${altairEpoch}`,
`bellatrix-${bellatrixEpoch}`,
`externalSigner-${withExternalSigner ? "yes" : "no"}`,
].join("_");

console.log(
Expand All @@ -62,7 +56,6 @@ for (const {beaconNodes, validatorClients, validatorsPerClient} of nodeCases) {
validatorsPerClient,
altairEpoch,
bellatrixEpoch,
withExternalSigner,
})
);
const env = new SimulationEnvironment({
Expand All @@ -74,7 +67,6 @@ for (const {beaconNodes, validatorClients, validatorsPerClient} of nodeCases) {
genesisSlotsDelay: (SLOTS_PER_EPOCH * runTill + 50) * testCases + 30,
bellatrixEpoch,
logFilesDir: join(logFilesDir, testIdStr),
externalSigner: withExternalSigner,
});
testCases += 1;

Expand Down
10 changes: 5 additions & 5 deletions packages/cli/test/utils/simulation/ExternalSignerServer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fastify from "fastify";
import {fromHexString, toHexString} from "@chainsafe/ssz";
import {fromHexString} from "@chainsafe/ssz";
import type {SecretKey} from "@chainsafe/bls/types";
import {EXTERNAL_SIGNER_BASE_PORT} from "./utils.js";

Expand All @@ -14,7 +14,7 @@ export class ExternalSignerServer {
constructor(secretKeys: SecretKey[]) {
const secretKeyMap = new Map<string, SecretKey>();
for (const secretKey of secretKeys) {
const pubkeyHex = toHexString(secretKey.toPublicKey().toBytes());
const pubkeyHex = secretKey.toPublicKey().toHex();
secretKeyMap.set(pubkeyHex, secretKey);
}
ExternalSignerServer.totalProcessCount++;
Expand All @@ -26,8 +26,8 @@ export class ExternalSignerServer {
return {status: "OK"};
});

this.server.get("/keys", async () => {
return {keys: Array.from(secretKeyMap.keys())};
this.server.get("/api/v1/eth2/publicKeys", async () => {
return [...secretKeyMap.keys()];
});

/* eslint-disable @typescript-eslint/naming-convention */
Expand All @@ -40,7 +40,7 @@ export class ExternalSignerServer {
/** Data to sign as a hex string */
signingRoot: string;
};
}>("/sign/:identifier", async (req) => {
}>("/api/v1/eth2/sign/:identifier", async (req) => {
const pubkeyHex: string = req.params.identifier;
const signingRootHex: string = req.body.signingRoot;

Expand Down
31 changes: 16 additions & 15 deletions packages/cli/test/utils/simulation/LodestarValidatorProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const LodestarValidatorProcess: ValidatorConstructor = class LodestarVali
readonly id: string;
readonly keyManagerApi: Api;
readonly secretKeys: SecretKey[] = [];
readonly externalSigner?: ExternalSignerServer;
readonly externalSigner: ExternalSignerServer;

private rootDir: string;
private clientIndex: number;
Expand Down Expand Up @@ -58,6 +58,9 @@ export const LodestarValidatorProcess: ValidatorConstructor = class LodestarVali
});
this.secretKeys = validatorSecretKeys;

// Split half of the keys to external signer
this.externalSigner = new ExternalSignerServer(this.secretKeys.slice(0, this.secretKeys.length / 2));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we define and set the ranges to be divided locally and externally as validables (and the default split as half/half)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also this.rcConfig["externalSigner.url"] = this.externalSigner.url; isn't required for this using this external signer?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also this.rcConfig["externalSigner.url"] = this.externalSigner.url; isn't required for this using this external signer?

oh ok since we now start keymanager to use this external signer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@g11tech Done.


this.rcConfig = ({
network: "dev",
preset: "minimal",
Expand All @@ -78,11 +81,6 @@ export const LodestarValidatorProcess: ValidatorConstructor = class LodestarVali
logLevel: "info",
} as unknown) as IValidatorCliArgs & IGlobalArgs;

if (this.params.externalSigner) {
this.externalSigner = new ExternalSignerServer(this.secretKeys);
this.rcConfig["externalSigner.url"] = this.externalSigner.url;
}

this.keyManagerApi = getClient(
{baseUrl: `http://${this.address}:${this.keyManagerPort}`},
{config: this.forkConfig}
Expand All @@ -94,20 +92,18 @@ export const LodestarValidatorProcess: ValidatorConstructor = class LodestarVali
await mkdir(`${this.rootDir}/keystores`);

await writeFile(join(this.rootDir, "password.txt"), "password");

await writeFile(join(this.rootDir, "rc_config.json"), JSON.stringify(this.rcConfig, null, 2));

for (const key of this.secretKeys) {
// Split half of the keys to the keymanager
for (const key of this.secretKeys.slice(this.secretKeys.length / 2)) {
const keystore = await Keystore.create("password", key.toBytes(), key.toPublicKey().toBytes(), "");
await writeFile(
join(this.rootDir, "keystores", `${key.toPublicKey().toHex()}.json`),
JSON.stringify(keystore.toObject(), null, 2)
);
}

if (this.externalSigner) {
await this.externalSigner.start();
}
await this.externalSigner.start();

console.log(`Starting lodestar validator "${this.id}".`, {dataDir: this.rootDir});

Expand All @@ -128,19 +124,24 @@ export const LodestarValidatorProcess: ValidatorConstructor = class LodestarVali
`Waiting for "${this.id}" to start.`
);

// Import half of the keys to the keymanager from external signer
await this.keyManagerApi.importRemoteKeys(
this.secretKeys
.slice(0, this.secretKeys.length / 2)
.map((sk) => ({pubkey: sk.toPublicKey().toHex(), url: this.externalSigner.url}))
);

console.log(`Validator "${this.id}" started.`);
}

async stop(): Promise<void> {
console.log(`Stopping validator "${this.id}".`);

if (this.externalSigner) {
await this.externalSigner.stop();
}

if (this.validatorProcess !== undefined) {
await closeChildProcess(this.validatorProcess);
}

await this.externalSigner.stop();
}

async ready(): Promise<boolean> {
Expand Down
2 changes: 0 additions & 2 deletions packages/cli/test/utils/simulation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ export type SimulationRequiredParams = {

export type SimulationOptionalParams = {
validatorsPerClient: number;
withExternalSigner: boolean;
secondsPerSlot: number;
genesisSlotsDelay: number;
anchorState?: BeaconStateAllForks;
externalSigner: boolean;
};

export type RunTimeSimulationParams = {
Expand Down
4 changes: 0 additions & 4 deletions packages/cli/test/utils/simulation/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,16 @@ export const logFilesDir = "test-logs";

export const defaultSimulationParams: SimulationOptionalParams = {
validatorsPerClient: 32,
withExternalSigner: false,
secondsPerSlot: 2,
// delay a bit so regular sync sees it's up to date and sync is completed from the beginning
// allow time for bls worker threads to warm up
genesisSlotsDelay: 30,
externalSigner: false,
};

export const getSimulationId = ({
beaconNodes,
validatorClients,
validatorsPerClient,
withExternalSigner,
altairEpoch,
bellatrixEpoch,
}: SimulationParams): string =>
Expand All @@ -46,7 +43,6 @@ export const getSimulationId = ({
`validatorsPerClient-${validatorsPerClient}`,
`altair-${altairEpoch}`,
`bellatrix-${bellatrixEpoch}`,
`externalSigner-${withExternalSigner ? "yes" : "no"}`,
].join("_");

export const spawnProcessAndWait = async (
Expand Down