Add a ncli tool for converting a regular keystore into a distributed one (#3634)
This commit is contained in:
parent
b3dc9e2c08
commit
a0a6dd2f63
1
Makefile
1
Makefile
|
@ -56,6 +56,7 @@ TOOLS := \
|
|||
logtrace \
|
||||
ncli \
|
||||
ncli_db \
|
||||
ncli_split_keystore \
|
||||
wss_sim \
|
||||
stack_sizes \
|
||||
nimbus_validator_client \
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
Loading…
Reference in New Issue