Add a ncli tool for converting a regular keystore into a distributed one (#3634)

This commit is contained in:
zah 2022-05-17 16:50:49 +03:00 committed by GitHub
parent b3dc9e2c08
commit a0a6dd2f63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 114 additions and 7 deletions

View File

@ -56,6 +56,7 @@ TOOLS := \
logtrace \
ncli \
ncli_db \
ncli_split_keystore \
wss_sim \
stack_sizes \
nimbus_validator_client \

View File

@ -868,7 +868,7 @@ type
AnyConf* = BeaconNodeConf | ValidatorClientConf | SigningNodeConf
proc defaultDataDir*(config: AnyConf): string =
proc defaultDataDir*[Conf](config: Conf): string =
let dataDir = when defined(windows):
"AppData" / "Roaming" / "Nimbus"
elif defined(macosx):
@ -981,10 +981,10 @@ proc parseCmdArg*(T: type enr.Record, p: string): T
func completeCmdArg*(T: type enr.Record, val: string): seq[string] =
return @[]
func validatorsDir*(config: AnyConf): string =
func validatorsDir*[Conf](config: Conf): string =
string config.validatorsDirFlag.get(InputDir(config.dataDir / "validators"))
func secretsDir*(config: AnyConf): string =
func secretsDir*[Conf](config: Conf): string =
string config.secretsDirFlag.get(InputDir(config.dataDir / "secrets"))
func walletsDir*(config: BeaconNodeConf): string =

View File

@ -287,7 +287,7 @@ proc installKeymanagerHandlers*(router: var RestRouter, node: BeaconNode) =
dres.get().pubkeys
var response: DeleteRemoteKeystoresResponse
for index, key in keys.pairs():
for index, key in keys:
let status = node.removeValidator(key)
response.data.add(status)
return RestApiResponse.jsonResponsePlain(response)

View File

@ -966,13 +966,13 @@ proc generateDistirbutedStore*(rng: var BrHmacDrbgContext,
remoteSignersUrls: seq[string],
threshold: uint32): Result[void, KeystoreGenerationError] =
var signers: seq[RemoteSignerInfo]
for (idx, share) in pairs(shares):
for idx, share in shares:
var password = KeystorePass.init ncrutils.toHex(getRandomBytes(rng, 32))
# remote signer shares
defer: burnMem(password)
? saveKeystore(rng,
shareValidatorDir & "/" & $idx,
shareSecretsDir & "/" & $idx,
shareValidatorDir / $share.id,
shareSecretsDir / $share.id,
share.key, share.key.toPubKey,
makeKeyPath(validatorIdx, signingKeyKind),
password.str,

View File

@ -0,0 +1,106 @@
import
std/os,
bearssl, nimcrypto/utils, confutils, eth/keys,
../beacon_chain/validators/keystore_management,
../beacon_chain/spec/[keystore, crypto],
../beacon_chain/conf
type
Config = object
threshold {.
desc: "Used to generate distributed keys"
name: "threshold" }: uint32
remoteSignersUrls {.
desc: "URLs of the remote signers"
name: "remote-signer" }: seq[string]
dataDir {.
defaultValue: config.defaultDataDir()
defaultValueDesc: ""
desc: "A Nimbus data directory"
name: "data-dir" }: InputDir
validatorsDirFlag* {.
desc: "A directory containing validator keystores"
name: "validators-dir" }: Option[InputDir]
secretsDirFlag* {.
desc: "A directory containing validator keystore passwords"
name: "secrets-dir" }: Option[InputDir]
key {.
desc: "A public key of the keystore"
name: "key" }: string
outDir {.
desc: "A directory to store the generated validator keystores"
name: "out-dir" }: OutDir
template valueOr(x: Option, elseBlock: untyped): untyped =
let val = x
if val.isSome:
val.get
else:
elseBlock
proc main =
let conf = load Config
if conf.threshold == 0:
error "The specified treshold must be greater than zero"
quit 1
if conf.remoteSignersUrls.len == 0:
error "Please specify at least one remote signer URL"
quit 1
if conf.threshold > conf.remoteSignersUrls.len.uint32:
error "The specified treshold must be lower or equal to the number of signers"
quit 1
var
rng = keys.newRng()
rngCtx = rng[]
let
validatorsDir = conf.validatorsDir
secretsDir = conf.secretsDir
keystore = loadKeystore(validatorsDir,
secretsDir,
conf.key, true).valueOr:
error "Can't load keystore", validatorsDir, secretsDir, pubkey = conf.key
quit 1
signingPubKey = keystore.pubkey
sharesCount = uint32 conf.remoteSignersUrls.len
shares = generateSecretShares(keystore.privateKey,
rngCtx,
conf.threshold,
sharesCount).valueOr:
error "Failed to generate distributed key: ",
threshold = conf.threshold, sharesCount
quit 1
if not signingPubKey.confirmShares(shares, rngCtx):
error "Secret shares can't reconstruct original signature. " &
"Distributed key will not be generated."
quit 1
let
outSharesDir = conf.outDir / "shares"
status = generateDistirbutedStore(
rngCtx,
shares,
signingPubKey,
0,
outSharesDir / "secrets",
outSharesDir / "validators",
string conf.outDir,
conf.remoteSignersUrls,
conf.threshold)
if status.isErr:
error "Failed to generate distributed keystore", err = status.error
quit 1
main()