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

Implement standard keymanager API #3522

Merged
merged 131 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
131 commits
Select commit Hold shift + click to select a range
81a194b
Add keymanager backend
dapplion Dec 13, 2021
abe2e98
Add keymanager server
dapplion Dec 14, 2021
2f3ed95
Add private local signer
dapplion Dec 14, 2021
d83df0c
Fix comment typo
dapplion Dec 14, 2021
dbec195
Update test types
dapplion Dec 14, 2021
706bebf
Update package.json and license
wemeetagain Dec 16, 2021
c3c220e
Hooking up the keymanager server - still manually registering a dummy…
dadepo Jan 12, 2022
f912c0f
Revert "Hooking up the keymanager server - still manually registering…
dadepo Jan 13, 2022
a1a42d8
using 9657 as default port for key manager server. Also not overridin…
dadepo Jan 18, 2022
9b1d99d
starting keymanager server also in dev
dadepo Jan 18, 2022
a04e798
Merge branch 'master' into dapplion/keymanager
dadepo Jan 19, 2022
615cf96
First stab at implementing deleting keys from persistant storage
dadepo Jan 19, 2022
a619f78
updating parsing of slashing data to make POST request work
dadepo Jan 20, 2022
e479d80
leaving some todo
dadepo Jan 20, 2022
4cceb2a
switching deleting file to async. Still need to take care of logging …
dadepo Jan 20, 2022
478b0fe
first dash at persisting keys for later restarts
dadepo Jan 20, 2022
33e894f
Merged master with remote signing functionality. App builds. More mod…
dadepo Jan 22, 2022
ec4e812
Adding (local signer for now) and removing of signer in ValidatorStore.
dadepo Jan 22, 2022
5f9ca26
deleting and adding working again with remote signer merged in
dadepo Jan 23, 2022
fddbd6e
fix lint errors
dadepo Jan 24, 2022
f5bf1fe
fix lint errors
dadepo Jan 24, 2022
2c48151
fix lint errors - finally
dadepo Jan 24, 2022
90e8d40
temp
dadepo Jan 26, 2022
43f108a
Moving keymanager to its own package to make the validator package no…
dadepo Jan 27, 2022
7bc3172
track test file
dadepo Jan 27, 2022
c24dd50
removing some outdated TODOs
dadepo Jan 27, 2022
f5dfc08
adding the generic server test for keymanager api
dadepo Jan 29, 2022
36a5d17
Merge branch 'dapplion/keymanager' of https://github.com/ChainSafe/lo…
dadepo Jan 29, 2022
80e43cc
removing an unused function and two empty test files
dadepo Jan 29, 2022
ebe0cff
keeping inline with existing pattern of using _config when config is …
dadepo Jan 30, 2022
217893a
Added first test for KeymanagerApi#listKeys
dadepo Jan 30, 2022
705f770
Added test for KeymanagerApi#importKeystores
dadepo Jan 31, 2022
81a7f7a
Added test for KeymanagerApi#deleteKeystores
dadepo Jan 31, 2022
022025a
move lock file to utils
dadepo Feb 1, 2022
ed3a000
making sure keystore are added and deleted in all scenarios
dadepo Feb 1, 2022
470b2fc
temp making some assertion less strict
dadepo Feb 1, 2022
543bef7
adding back matchers in the test
dadepo Feb 1, 2022
a497722
removing e2e test in script since none yet
dadepo Feb 1, 2022
9418cdb
On delete remove key from internal list of keys known my the keymanager
dadepo Feb 1, 2022
5849cf6
first shot at adding bearer authentication for keymanager server
dadepo Feb 3, 2022
e5ff846
Using async pattern again so as to fix test that only fails on ci
dadepo Feb 3, 2022
5b79d1d
log location of keymanager's bearer token on startup
dadepo Feb 3, 2022
1fdf81e
Undoing the addition of lockfile to lodestar-util as it is a package …
dadepo Feb 4, 2022
417740d
importing lockfile in test
dadepo Feb 4, 2022
bc1fea6
Stubbing out the keystore. All tests should now pass on CI
dadepo Feb 4, 2022
87d1b80
resolve conflicts after merging master in
dadepo Feb 4, 2022
958b16e
remove duplicated start of validator
dadepo Feb 5, 2022
88ad699
When using dev command, make it actually possible to not run a valida…
dadepo Feb 6, 2022
2a74c86
Passing in the directory where the keymanager's bearer token will be …
dadepo Feb 6, 2022
42376cf
Properly setting the path to keystore file to be deleted
dadepo Feb 6, 2022
1ad3e97
adding methods to remove signer from various duties, exposing and cal…
dadepo Feb 7, 2022
dc168c6
Added tests for BlockDutiesService#remove
dadepo Feb 7, 2022
6fb876b
fix linting errors
dadepo Feb 7, 2022
d7141da
Added tests for AttestationDutiesService#remove
dadepo Feb 8, 2022
f02d2e3
Added tests for SyncCommitteeDutiesService#remove
dadepo Feb 8, 2022
3bcd3ec
Added test to directly test IndicesService
dadepo Feb 8, 2022
5928a1b
update test to confirm unremoved pubkey is not affected by the remove…
dadepo Feb 9, 2022
bc6601c
Added the scaffolding to run e2e test that makes use of the keymanager
dadepo Feb 9, 2022
b8fb95e
shut down node and validators in keymanager e2e test
dadepo Feb 9, 2022
abdbfdb
Making sure by default bearer authentication is used for keymanager api
dadepo Feb 10, 2022
3e01de3
Adding e2e for keymanager api
dadepo Feb 11, 2022
3fb6746
adding some eslint ignore comments
dadepo Feb 11, 2022
56fc9ea
merging in current state of master and fixing merge conflicts
dadepo Feb 12, 2022
b059501
Fix linting errors
dadepo Feb 12, 2022
889f519
Processing some todos
dadepo Feb 12, 2022
cb87eba
Process left TODOs
dadepo Feb 13, 2022
2dc63d1
log a warning if kemanager started without auth
dadepo Feb 13, 2022
d2d029f
fix compilation error when running sim:singleThread test
dadepo Feb 14, 2022
87a1ae8
import all modules from same package in same line
dadepo Feb 14, 2022
1a031b8
fix compilation error due to import
dadepo Feb 14, 2022
b351826
Added logger to KeymanagerApi
dadepo Feb 14, 2022
a2b9757
Fixed compilation error in key managers e2e test due to changes that …
dadepo Feb 14, 2022
c70966c
removing TODO after deciding to action needed
dadepo Feb 14, 2022
555b50e
removing download-spec-tests from keymanager-server script
dadepo Feb 15, 2022
bc31a1f
test request is denied if no auth for keymanager
dadepo Feb 15, 2022
204536f
trying closing keymanager before beacon node
dadepo Feb 15, 2022
416fa12
setting port right
dadepo Feb 15, 2022
6e966b9
Some improvement to the keymanager e2e test
dadepo Feb 16, 2022
92e6d5d
Added signing to e2e test for key manager
dadepo Feb 16, 2022
a668539
Added support for interactions with remote signer validators. Removed…
dadepo Feb 16, 2022
e9d6da7
optimise imports
dadepo Feb 18, 2022
6a3405e
optimize some tests assertion
dadepo Feb 18, 2022
e6353a5
minor correction to capitalisation
dadepo Feb 18, 2022
b4eb5f6
register callback to delete locks in same loop that adds to signers
dadepo Feb 18, 2022
69ee4d7
fix compilation error
dadepo Feb 18, 2022
fec9913
adding lockfile as dependency following alphabetical order
dadepo Feb 21, 2022
f70caa1
Improving the registering of shutdown callbacks
dadepo Feb 21, 2022
44025b0
moving keymanager options out of beacon node options
dadepo Feb 21, 2022
50adc04
having back default value for startValidators flag
dadepo Feb 21, 2022
4672ca8
Removed unnecessary comment
dadepo Feb 21, 2022
3e93f1a
removed the parse-numbers setting
dadepo Feb 21, 2022
12be734
Switching to making imported keystore path deterministic by pubkey
dadepo Feb 22, 2022
7a324ab
Using Array constructor with length is more efficient
dadepo Feb 22, 2022
8dbdaaf
Move some keystore test utility function to a seperate file
dadepo Feb 22, 2022
a52e891
Removed some more suppress comments
dadepo Feb 22, 2022
9cf1003
Removed unnecessary dependency
dadepo Feb 22, 2022
7e35c77
using 5062 as default port for keymanager
dadepo Feb 22, 2022
579802e
Improve keymanager and keymanager e2e tests
dadepo Feb 22, 2022
1a3a02e
Removed unnecessary test utility function
dadepo Feb 23, 2022
c2446ce
Removed the use of mapvalues
dadepo Feb 24, 2022
5483478
Not exposing duties
dadepo Feb 24, 2022
be3f098
Minor comment improvement
dadepo Feb 24, 2022
8e2411c
Have slashing protection be part of validator and use that in the key…
dadepo Feb 24, 2022
b8fa263
Remove getSignerLocal
dapplion Feb 25, 2022
7214b53
switch use of forEach for for-of
dadepo Feb 25, 2022
3c1d8a8
revert changes to local.md
dadepo Feb 25, 2022
ef4f9fd
optimise import order
dadepo Feb 25, 2022
7b9eee5
Moved typing info for lockfile to devDependencies
dadepo Feb 28, 2022
eebbbe4
Some renaming
dadepo Feb 28, 2022
beed866
replace join with path.join for clarity
dadepo Feb 28, 2022
c668d47
setting derivation path
dadepo Feb 28, 2022
38fcfd4
Introduced a utility for keystore file, that is used both in importin…
dadepo Feb 28, 2022
e8380fc
having duties service classes back to private
dadepo Feb 28, 2022
568ade7
re-adding test:unit
dadepo Feb 28, 2022
5be26b9
switching to using path.join
dadepo Feb 28, 2022
bd74673
Introduced a more robust cleanup for lightclient.test.ts
dadepo Mar 1, 2022
abde51c
import optimisation
dadepo Mar 1, 2022
7bb2cfa
putting all closing of nodes/validators into afterEach call
dadepo Mar 1, 2022
1928930
Merge in latest master and resolved conflicts
dadepo Mar 3, 2022
9790834
temp skip keymanager e2e test
dadepo Mar 3, 2022
3ac7900
switching node port back to 9596. It should not be any problem as lon…
dadepo Mar 3, 2022
3e9f0e7
switch test port to 19596 see if this fixes tests
dadepo Mar 3, 2022
a5faad2
Immediately register clean up for servers
dadepo Mar 3, 2022
58cb2f5
Temp skip a failing test
dadepo Mar 3, 2022
cfbfd85
Using tmp dir for keeping bearer token for test cases where keymanage…
dadepo Mar 3, 2022
beaddd9
move the lockfile to keymanager
dadepo Mar 4, 2022
ba693b1
Added tests to cover bearer token authentication flow
dadepo Mar 5, 2022
86bde81
Setting derivationPath back to empty string. Implementing getting der…
dadepo Mar 8, 2022
c69b5e3
Merge master and fix conflicts
dadepo Mar 14, 2022
78189f4
Fix type error
dadepo Mar 15, 2022
e261589
Merge branch 'master' into dapplion/keymanager
dadepo Mar 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions docs/usage/local.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ To quickly test and run Lodestar we recommend starting a local testnet. We recom
Run a beacon node, with 8 validators with the following command.

```bash
./lodestar dev --genesisValidators 8 --genesisTime 1578787200 --enr.ip 127.0.0.1 --rootDir </path/to/node1> --reset
./lodestar dev --genesisValidators 8 --genesisTime 1578787200 --startValidators 0:8 --enr.ip 127.0.0.1 --rootDir </path/to/node1> --reset
```

`--genesisValidators` and `--genesisTime` define the genesis state of the beacon chain. `--rootDir` defines a path where
Expand All @@ -25,8 +25,7 @@ This would be used to connect from the second node.
Start the second node without starting any validators and connect to the first node by supplying the copied `enr` value:

```bash
./lodestar dev --startValidators 0:0 \
--genesisValidators 8 --genesisTime 1578787200 \
./lodestar dev --genesisValidators 8 --genesisTime 1578787200 \
--rootDir /path/to/node2 \
--port 9001 \
--api.rest.port 9597 \
Expand All @@ -41,7 +40,7 @@ the `--startValidators` option. Passing a value of `0:0` means no validators sho
Also, take note that the values of `--genesisValidators` and `--genesisTime` must be the same as the ones passed to the first node in other for the two nodes
to have the same beacon chain.

Finally `--port` and `--api.rest.port` are supplied since the default values will already be in use by the first node.
Also `--port` and `--api.rest.port` are supplied since the default values will already be in use by the first node.

The `--network.connectToDiscv5Bootnodes` flags needs to be set to true as this is needed to allow connection to boot enrs on local devnet.
The exact enr of node to connect to is then supplied via the `--network.discv5.bootEnrs` flag.
Expand Down
1 change: 1 addition & 0 deletions packages/api/keymanager.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./lib/keymanager";
2 changes: 2 additions & 0 deletions packages/api/keymanager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line @typescript-eslint/no-require-imports
module.exports = require("./lib/keymanager");
1 change: 1 addition & 0 deletions packages/api/keymanager_server.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./lib/keymanager/server";
2 changes: 2 additions & 0 deletions packages/api/keymanager_server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// eslint-disable-next-line @typescript-eslint/no-require-imports
module.exports = require("./lib/keymanager/server");
10 changes: 10 additions & 0 deletions packages/api/src/keymanager/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {IHttpClient, generateGenericJsonClient} from "../client/utils";
import {Api, ReqTypes, routesData, getReqSerializers, getReturnTypes} from "./routes";
import {IChainForkConfig} from "@chainsafe/lodestar-config";

export function getClient(_config: IChainForkConfig, httpClient: IHttpClient): Api {
const reqSerializers = getReqSerializers();
const returnTypes = getReturnTypes();
// All routes return JSON, use a client auto-generator
return generateGenericJsonClient<Api, ReqTypes>(routesData, reqSerializers, returnTypes, httpClient);
}
16 changes: 16 additions & 0 deletions packages/api/src/keymanager/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {IChainForkConfig} from "@chainsafe/lodestar-config";
import {HttpClient, HttpClientOptions} from "../client";
import {IHttpClient} from "../client/utils";
import {Api} from "./routes";
import * as keymanager from "./client";

export {ImportStatus, DeletionStatus, KeystoreStr, SlashingProtectionData, PubkeyHex, Api} from "./routes";

/**
* REST HTTP client for all keymanager routes
*/
export function getClient(config: IChainForkConfig, opts: HttpClientOptions, httpClient?: IHttpClient): Api {
if (!httpClient) httpClient = new HttpClient(opts);

return keymanager.getClient(config, httpClient);
}
161 changes: 161 additions & 0 deletions packages/api/src/keymanager/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import {ReturnTypes, RoutesData, Schema, reqEmpty, ReqSerializers, ReqEmpty, jsonType} from "../utils";

export enum ImportStatus {
/** Keystore successfully decrypted and imported to keymanager permanent storage */
imported = "imported",
/** Keystore's pubkey is already known to the keymanager */
duplicate = "duplicate",
/** Any other status different to the above: decrypting error, I/O errors, etc. */
error = "error",
}

export enum DeletionStatus {
/** key was active and removed */
deleted = "deleted",
/** slashing protection data returned but key was not active */
not_active = "not_active",
/** key was not found to be removed, and no slashing data can be returned */
not_found = "not_found",
/** unexpected condition meant the key could not be removed (the key was actually found, but we couldn't stop using it) - this would be a sign that making it active elsewhere would almost certainly cause you headaches / slashing conditions etc. */
error = "error",
}

/**
* JSON serialized representation of a single keystore in EIP-2335: BLS12-381 Keystore format.
* ```
* '{"version":4,"uuid":"9f75a3fa-1e5a-49f9-be3d-f5a19779c6fa","path":"m/12381/3600/0/0/0","pubkey":"0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a","crypto":{"kdf":{"function":"pbkdf2","params":{"dklen":32,"c":262144,"prf":"hmac-sha256","salt":"8ff8f22ef522a40f99c6ce07fdcfc1db489d54dfbc6ec35613edf5d836fa1407"},"message":""},"checksum":{"function":"sha256","params":{},"message":"9678a69833d2576e3461dd5fa80f6ac73935ae30d69d07659a709b3cd3eddbe3"},"cipher":{"function":"aes-128-ctr","params":{"iv":"31b69f0ac97261e44141b26aa0da693f"},"message":"e8228bafec4fcbaca3b827e586daad381d53339155b034e5eaae676b715ab05e"}}}'
* ```
*/
export type KeystoreStr = string;

/**
* JSON serialized representation of the slash protection data in format defined in EIP-3076: Slashing Protection Interchange Format.
* ```
* '{"metadata":{"interchange_format_version":"5","genesis_validators_root":"0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2"},"data":[{"pubkey":"0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a","signed_blocks":[],"signed_attestations":[]}]}'
* ```
*/
export type SlashingProtectionData = string;

/**
* The validator's BLS public key, uniquely identifying them. _48-bytes, hex encoded with 0x prefix, case insensitive._
* ```
* "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a"
* ```
*/
export type PubkeyHex = string;

type Statuses<Status> = {
status: Status;
message?: string;
}[];

type ImportKeystoresReq = {
keystores: KeystoreStr[];
passwords: string[];
slashingProtection: SlashingProtectionData;
};

type ListKeysResponse = {
validatingPubkey: PubkeyHex;
/** The derivation path (if present in the imported keystore) */
derivationPath?: string;
/** The key associated with this pubkey cannot be deleted from the API */
readonly?: boolean;
};

export type Api = {
/**
* List all validating pubkeys known to and decrypted by this keymanager binary
*
* https://github.com/ethereum/keymanager-APIs/blob/0c975dae2ac6053c8245ebdb6a9f27c2f114f407/keymanager-oapi.yaml
*/
listKeys(): Promise<{
data: ListKeysResponse[];
}>;

/**
* Import keystores generated by the Eth2.0 deposit CLI tooling. `passwords[i]` must unlock `keystores[i]`.
*
* Users SHOULD send slashing_protection data associated with the imported pubkeys. MUST follow the format defined in
* EIP-3076: Slashing Protection Interchange Format.
*
* @param keystores JSON-encoded keystore files generated with the Launchpad
* @param passwords Passwords to unlock imported keystore files. `passwords[i]` must unlock `keystores[i]`
* @param slashingProtection Slashing protection data for some of the keys of `keystores`
* @returns Status result of each `request.keystores` with same length and order of `request.keystores`
*
* https://github.com/ethereum/keymanager-APIs/blob/0c975dae2ac6053c8245ebdb6a9f27c2f114f407/keymanager-oapi.yaml
*/
importKeystores(
keystoresStr: KeystoreStr[],
passwords: string[],
slashingProtectionStr: SlashingProtectionData
): Promise<{
data: Statuses<ImportStatus>;
}>;

/**
* DELETE must delete all keys from `request.pubkeys` that are known to the keymanager and exist in its
* persistent storage. Additionally, DELETE must fetch the slashing protection data for the requested keys from
* persistent storage, which must be retained (and not deleted) after the response has been sent. Therefore in the
* case of two identical delete requests being made, both will have access to slashing protection data.
*
* In a single atomic sequential operation the keymanager must:
* 1. Guarantee that key(s) can not produce any more signature; only then
* 2. Delete key(s) and serialize its associated slashing protection data
*
* DELETE should never return a 404 response, even if all pubkeys from request.pubkeys have no extant keystores
* nor slashing protection data.
*
* Slashing protection data must only be returned for keys from `request.pubkeys` for which a
* `deleted` or `not_active` status is returned.
*
* @param pubkeys List of public keys to delete.
* @returns Deletion status of all keys in `request.pubkeys` in the same order.
*
* https://github.com/ethereum/keymanager-APIs/blob/0c975dae2ac6053c8245ebdb6a9f27c2f114f407/keymanager-oapi.yaml
*/
deleteKeystores(
pubkeysHex: string[]
): Promise<{
data: Statuses<DeletionStatus>;
slashingProtection: SlashingProtectionData;
}>;
};

export const routesData: RoutesData<Api> = {
listKeys: {url: "/eth/v1/keystores", method: "GET"},
importKeystores: {url: "/eth/v1/keystores", method: "POST"},
deleteKeystores: {url: "/eth/v1/keystores", method: "DELETE"},
};

export type ReqTypes = {
listKeys: ReqEmpty;
importKeystores: {body: ImportKeystoresReq};
deleteKeystores: {body: {pubkeys: string[]}};
};

export function getReqSerializers(): ReqSerializers<Api, ReqTypes> {
return {
listKeys: reqEmpty,
importKeystores: {
writeReq: (keystores, passwords, slashingProtection) => ({body: {keystores, passwords, slashingProtection}}),
parseReq: ({body: {keystores, passwords, slashingProtection}}) => [keystores, passwords, slashingProtection],
schema: {body: Schema.Object},
},
deleteKeystores: {
writeReq: (pubkeys) => ({body: {pubkeys}}),
parseReq: ({body: {pubkeys}}) => [pubkeys],
schema: {body: Schema.Object},
},
};
}

/* eslint-disable @typescript-eslint/naming-convention */
export function getReturnTypes(): ReturnTypes<Api> {
return {
listKeys: jsonType(),
importKeystores: jsonType(),
deleteKeystores: jsonType(),
};
}
8 changes: 8 additions & 0 deletions packages/api/src/keymanager/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {IChainForkConfig} from "@chainsafe/lodestar-config";
import {ServerRoutes, getGenericJsonServer} from "../server/utils";
import {Api, ReqTypes, routesData, getReturnTypes, getReqSerializers} from "./routes";

export function getRoutes(config: IChainForkConfig, api: Api): ServerRoutes<Api, ReqTypes> {
// All routes return JSON, use a server auto-generator
return getGenericJsonServer<Api, ReqTypes>({routesData, getReturnTypes, getReqSerializers}, config, api);
}
2 changes: 1 addition & 1 deletion packages/api/src/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export type RouteGroupDefinition<

export type RouteDef = {
url: string;
method: "GET" | "POST";
method: "GET" | "POST" | "DELETE";
};

export type ReqGeneric = {
Expand Down
32 changes: 32 additions & 0 deletions packages/api/test/unit/keymanager.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {config} from "@chainsafe/lodestar-config/default";
import {Api, DeletionStatus, ImportStatus, ReqTypes} from "../../src/keymanager/routes";
import {getClient} from "../../src/keymanager/client";
import {getRoutes} from "../../src/keymanager/server";
import {runGenericServerTest} from "../utils/genericServerTest";

describe("keymanager", () => {
runGenericServerTest<Api, ReqTypes>(config, getClient, getRoutes, {
listKeys: {
args: [],
res: {
data: [
{
validatingPubkey:
// randomly pregenerated pubkey
"0x84105a985058fc8740a48bf1ede9d223ef09e8c6b1735ba0a55cf4a9ff2ff92376b778798365e488dab07a652eb04576",
derivationPath: "m/12381/3600/0/0/0",
readonly: false,
},
],
},
},
importKeystores: {
args: [["key1"], ["pass1"], "slash_protection"],
res: {data: [{status: ImportStatus.imported}]},
},
deleteKeystores: {
args: [["key1"]],
res: {data: [{status: DeletionStatus.deleted}], slashingProtection: "slash_protection"},
},
});
});
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@
"@chainsafe/abort-controller": "^3.0.1",
"@chainsafe/bls": "6.0.3",
"@chainsafe/bls-keygen": "^0.3.0",
"@chainsafe/bls-keystore": "2.0.0",
"@chainsafe/bls-keystore": "^2.0.0",
"@chainsafe/blst": "^0.2.4",
"@chainsafe/discv5": "^0.6.7",
"@chainsafe/lodestar": "^0.36.0",
"@chainsafe/lodestar-api": "^0.36.0",
"@chainsafe/lodestar-beacon-state-transition": "^0.36.0",
"@chainsafe/lodestar-config": "^0.36.0",
"@chainsafe/lodestar-db": "^0.36.0",
"@chainsafe/lodestar-keymanager-server": "^0.36.0",
"@chainsafe/lodestar-params": "^0.36.0",
"@chainsafe/lodestar-types": "^0.36.0",
"@chainsafe/lodestar-utils": "^0.36.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {SlashingProtection, Validator} from "@chainsafe/lodestar-validator";
import {SignerType} from "@chainsafe/lodestar-validator";
import {SignerType, SlashingProtection, Validator} from "@chainsafe/lodestar-validator";
import {readdirSync} from "node:fs";
import {LevelDbController} from "@chainsafe/lodestar-db";
import inquirer from "inquirer";
Expand Down
12 changes: 10 additions & 2 deletions packages/cli/src/cmds/dev/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@ import {Options} from "yargs";
import {ICliCommandOptions} from "../../util";
import {beaconOptions, IBeaconArgs} from "../beacon/options";
import {beaconNodeOptions} from "../../options";
import {IValidatorCliArgs, validatorOptions} from "../validator/options";
import {KeymanagerArgs, keymanagerOptions} from "../../options/keymanagerOptions";

interface IDevOwnArgs {
type IDevOwnArgs = {
genesisEth1Hash?: string;
genesisValidators?: number;
startValidators?: string;
genesisTime?: number;
reset?: boolean;
server: string;
}
} & KeymanagerArgs &
Pick<IValidatorCliArgs, "importKeystoresPath" | "importKeystoresPassword">;

const devOwnOptions: ICliCommandOptions<IDevOwnArgs> = {
...keymanagerOptions,
...{
importKeystoresPath: validatorOptions["importKeystoresPath"],
importKeystoresPassword: validatorOptions["importKeystoresPassword"],
},
genesisEth1Hash: {
description: "If present it will create genesis with this eth1 hash.",
type: "string",
Expand Down
23 changes: 22 additions & 1 deletion packages/cli/src/cmds/validator/handler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {AbortController} from "@chainsafe/abort-controller";
import {getClient} from "@chainsafe/lodestar-api";
import {Validator, SlashingProtection, Signer, SignerType} from "@chainsafe/lodestar-validator";
import {LevelDbController} from "@chainsafe/lodestar-db";
import {SignerType, Signer, SlashingProtection, Validator} from "@chainsafe/lodestar-validator";
import {KeymanagerServer, KeymanagerApi} from "@chainsafe/lodestar-keymanager-server";
import {getBeaconConfigFromArgs} from "../../config";
import {IGlobalArgs} from "../../options";
import {YargsError, getDefaultGraffiti, initBLS, mkdir, getCliLogger} from "../../util";
Expand Down Expand Up @@ -102,4 +103,24 @@ export async function validatorHandler(args: IValidatorCliArgs & IGlobalArgs): P

onGracefulShutdownCbs.push(async () => await validator.stop());
await validator.start();

// Start keymanager API backend
// Only if keymanagerEnabled flag is set to true and at least one keystore path is supplied
const firstImportKeystorePath = args.importKeystoresPath?.[0];
if (args.keymanagerEnabled && firstImportKeystorePath) {
const keymanagerApi = new KeymanagerApi(logger, validator, firstImportKeystorePath);

const keymanagerServer = new KeymanagerServer(
{
host: args.keymanagerHost,
port: args.keymanagerPort,
cors: args.keymanagerCors,
isAuthEnabled: args.keymanagerAuthEnabled,
tokenDir: dbPath,
},
{config, logger, api: keymanagerApi}
);
onGracefulShutdownCbs.push(() => keymanagerServer.close());
dapplion marked this conversation as resolved.
Show resolved Hide resolved
await keymanagerServer.listen();
}
}
3 changes: 1 addition & 2 deletions packages/cli/src/cmds/validator/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,14 @@ import {CoordType, PublicKey, SecretKey} from "@chainsafe/bls";
import {deriveEth2ValidatorKeys, deriveKeyFromMnemonic} from "@chainsafe/bls-keygen";
import {interopSecretKey} from "@chainsafe/lodestar-beacon-state-transition";
import {externalSignerGetKeys} from "@chainsafe/lodestar-validator";
import {LOCK_FILE_EXT, getLockFile} from "@chainsafe/lodestar-keymanager-server";
import {defaultNetwork, IGlobalArgs} from "../../options";
import {parseRange, stripOffNewlines, YargsError} from "../../util";
import {getLockFile} from "../../util/lockfile";
import {ValidatorDirManager} from "../../validatorDir";
import {getAccountPaths} from "../account/paths";
import {IValidatorCliArgs} from "./options";
import {fromHexString} from "@chainsafe/ssz";

const LOCK_FILE_EXT = ".lock";
const depositDataPattern = new RegExp(/^deposit_data-\d+\.json$/gi);

export async function getLocalSecretKeys(
Expand Down
Loading