better error messages for keystore operations (#2812)

in particular, incluse os error string
This commit is contained in:
Jacek Sieka 2021-08-27 18:53:21 +02:00 committed by GitHub
parent 01596c45dd
commit 6a4bf98ea2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 35 additions and 38 deletions

View File

@ -307,12 +307,21 @@ iterator validatorKeys*(config: BeaconNodeConf|ValidatorClientConf): ValidatorPr
quit 1 quit 1
type type
KeystoreGenerationError = enum KeystoreGenerationErrorKind = enum
RandomSourceDepleted,
FailedToCreateValidatorDir FailedToCreateValidatorDir
FailedToCreateSecretsDir FailedToCreateSecretsDir
FailedToCreateSecretFile FailedToCreateSecretFile
FailedToCreateKeystoreFile FailedToCreateKeystoreFile
KeystoreGenerationError* = object
case kind*: KeystoreGenerationErrorKind
of FailedToCreateValidatorDir, FailedToCreateSecretsDir,
FailedToCreateSecretFile, FailedToCreateKeystoreFile:
error*: string
proc mapErrTo[T, E](r: Result[T, E], v: static KeystoreGenerationErrorKind):
Result[T, KeystoreGenerationError] =
r.mapErr(proc (e: E): KeystoreGenerationError =
KeystoreGenerationError(kind: v, error: $e))
proc loadNetKeystore*(keyStorePath: string, proc loadNetKeystore*(keyStorePath: string,
insecurePwd: Option[string]): Option[lcrypto.PrivateKey] = insecurePwd: Option[string]): Option[lcrypto.PrivateKey] =
@ -366,19 +375,18 @@ proc saveNetKeystore*(rng: var BrHmacDrbgContext, keyStorePath: string,
else: else:
let prompt = "Please enter NEW password to lock network key storage: " let prompt = "Please enter NEW password to lock network key storage: "
let confirm = "Please confirm, network key storage password: " let confirm = "Please confirm, network key storage password: "
let res = keyboardCreatePassword(prompt, confirm) ? keyboardCreatePassword(prompt, confirm).mapErrTo(
if res.isErr(): FailedToCreateKeystoreFile)
return err(FailedToCreateKeystoreFile)
res.get()
let keyStore = createNetKeystore(kdfScrypt, rng, netKey, let keyStore = createNetKeystore(kdfScrypt, rng, netKey,
KeystorePass.init password) KeystorePass.init password)
var encodedStorage: string var encodedStorage: string
try: try:
encodedStorage = Json.encode(keyStore) encodedStorage = Json.encode(keyStore)
except SerializationError: except SerializationError as exc:
error "Could not serialize network key storage", key_path = keyStorePath error "Could not serialize network key storage", key_path = keyStorePath
return err(FailedToCreateKeystoreFile) return err(KeystoreGenerationError(
kind: FailedToCreateKeystoreFile, error: exc.msg))
let res = secureWriteFile(keyStorePath, encodedStorage) let res = secureWriteFile(keyStorePath, encodedStorage)
if res.isOk(): if res.isOk():
@ -386,7 +394,7 @@ proc saveNetKeystore*(rng: var BrHmacDrbgContext, keyStorePath: string,
else: else:
error "Could not write to network key storage file", error "Could not write to network key storage file",
key_path = keyStorePath key_path = keyStorePath
err(FailedToCreateKeystoreFile) res.mapErrTo(FailedToCreateKeystoreFile)
proc saveKeystore(rng: var BrHmacDrbgContext, proc saveKeystore(rng: var BrHmacDrbgContext,
validatorsDir, secretsDir: string, validatorsDir, secretsDir: string,
@ -408,25 +416,17 @@ proc saveKeystore(rng: var BrHmacDrbgContext,
var encodedStorage: string var encodedStorage: string
try: try:
encodedStorage = Json.encode(keyStore) encodedStorage = Json.encode(keyStore)
except SerializationError: except SerializationError as e:
error "Could not serialize keystorage", key_path = keystoreFile error "Could not serialize keystorage", key_path = keystoreFile
return err(FailedToCreateKeystoreFile) return err(KeystoreGenerationError(
kind: FailedToCreateKeystoreFile, error: e.msg))
let vres = secureCreatePath(validatorDir) ? secureCreatePath(validatorDir).mapErrTo(FailedToCreateValidatorDir)
if vres.isErr(): ? secureCreatePath(secretsDir).mapErrTo(FailedToCreateSecretsDir)
return err(FailedToCreateValidatorDir) ? secureWriteFile(secretsDir / keyName, password.str).mapErrTo(
FailedToCreateSecretFile)
let sres = secureCreatePath(secretsDir) ? secureWriteFile(keystoreFile, encodedStorage).mapErrTo(
if sres.isErr(): FailedToCreateKeystoreFile)
return err(FailedToCreateSecretsDir)
let swres = secureWriteFile(secretsDir / keyName, password.str)
if swres.isErr():
return err(FailedToCreateSecretFile)
let kwres = secureWriteFile(keystoreFile, encodedStorage)
if kwres.isErr():
return err(FailedToCreateKeystoreFile)
ok() ok()
@ -476,12 +476,11 @@ proc saveWallet*(wallet: Wallet, outWalletPath: string): Result[void, string] =
except SerializationError: except SerializationError:
return err("Could not serialize wallet") return err("Could not serialize wallet")
let pres = secureCreatePath(walletDir) ? secureCreatePath(walletDir).mapErr(proc(e: auto): string =
if pres.isErr(): "Could not create wallet directory [" & walletDir & "]: " & $e)
return err("Could not create wallet directory [" & walletDir & "]")
let wres = secureWriteFile(outWalletPath, encodedWallet) ? secureWriteFile(outWalletPath, encodedWallet).mapErr(proc(e: auto): string =
if wres.isErr(): "Could not write wallet to file [" & outWalletPath & "]: " & $e)
return err("Could not write wallet to file [" & outWalletPath & "]")
ok() ok()
@ -570,7 +569,8 @@ proc importKeystoresFromDir*(rng: var BrHmacDrbgContext,
if status.isOk: if status.isOk:
notice "Keystore imported", file notice "Keystore imported", file
else: else:
error "Failed to import keystore", file, err = status.error error "Failed to import keystore",
file, validatorsDir, secretsDir, err = status.error
else: else:
error "Imported keystore holds invalid key", file, err = privKey.error error "Imported keystore holds invalid key", file, err = privKey.error
break break
@ -618,10 +618,7 @@ proc pickPasswordAndSaveWallet(rng: var BrHmacDrbgContext,
block: block:
let prompt = "Please enter a password: " let prompt = "Please enter a password: "
let confirm = "Please repeat the password: " let confirm = "Please repeat the password: "
let res = keyboardCreatePassword(prompt, confirm) ? keyboardCreatePassword(prompt, confirm).mapErr(proc(e: auto): string = $e)
if res.isErr():
return err($res.error)
res.get()
defer: burnMem(password) defer: burnMem(password)
var name: WalletName var name: WalletName
@ -771,7 +768,7 @@ proc createWalletInteractively*(
burnMem(recoveryPassword.get) burnMem(recoveryPassword.get)
if recoveryPassword.isErr: if recoveryPassword.isErr:
fatal "Failed to read password from stdin" fatal "Failed to read password from stdin: "
quit 1 quit 1
var keystorePass = KeystorePass.init recoveryPassword.get var keystorePass = KeystorePass.init recoveryPassword.get