2022-05-17 13:50:49 +00:00
|
|
|
import
|
|
|
|
std/os,
|
2022-06-21 08:29:16 +00:00
|
|
|
nimcrypto/utils, confutils, eth/keys,
|
2022-05-17 13:50:49 +00:00
|
|
|
../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()
|