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

Use Mina_user_error for daemon bootup failures #6741

Merged
merged 14 commits into from
Nov 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
73 changes: 41 additions & 32 deletions src/app/cli/src/coda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ let setup_daemon logger =
| None ->
return None
| Some s ->
Secrets.Libp2p_keypair.Terminal_stdin.read_from_env_exn s
Secrets.Libp2p_keypair.Terminal_stdin.read_from_env_exn
~which:"libp2p keypair" s
|> Deferred.map ~f:Option.some )
in
let%bind () =
Expand Down Expand Up @@ -505,12 +506,9 @@ let setup_daemon logger =
| Error err -> (
match handle_missing with
| `Must_exist ->
[%log fatal]
"Failed reading configuration from $config_file: $error"
~metadata:
[ ("config_file", `String config_file)
; ("error", Error_json.error_to_yojson err) ] ;
Error.raise err
Mina_user_error.raisef ~where:"reading configuration file"
"The configuration file %s could not be read:\n%s"
config_file (Error.to_string_hum err)
| `May_be_missing ->
[%log warn]
"Could not read configuration from $config_file: $error"
Expand Down Expand Up @@ -650,33 +648,34 @@ let setup_daemon logger =
; transaction_pool_diff= log_transaction_pool_diff
; new_state= log_received_blocks }
in
let json_to_publickey_compressed_option json =
let json_to_publickey_compressed_option which json =
YJ.Util.to_string_option json
|> Option.bind ~f:(fun pk_str ->
match Public_key.Compressed.of_base58_check pk_str with
| Ok key ->
Some key
| Error e ->
[%log error] "Error decoding public key ($key): $error"
~metadata:
[ ("key", `String pk_str)
; ("error", Error_json.error_to_yojson e) ] ;
None )
| Error _e ->
Mina_user_error.raisef ~where:"decoding a public key"
"The %s public key %s could not be decoded." which pk_str
)
in
let run_snark_worker_flag =
maybe_from_config json_to_publickey_compressed_option
maybe_from_config
(json_to_publickey_compressed_option "snark worker")
"run-snark-worker" run_snark_worker_flag
in
let run_snark_coordinator_flag =
maybe_from_config json_to_publickey_compressed_option
maybe_from_config
(json_to_publickey_compressed_option "snark coordinator")
"run-snark-coordinator" run_snark_coordinator_flag
in
let snark_worker_parallelism_flag =
maybe_from_config YJ.Util.to_int_option "snark-worker-parallelism"
snark_worker_parallelism_flag
in
let coinbase_receiver_flag =
maybe_from_config json_to_publickey_compressed_option
maybe_from_config
(json_to_publickey_compressed_option "coinbase receiver")
"coinbase-receiver" coinbase_receiver_flag
in
let%bind external_ip =
Expand All @@ -697,7 +696,8 @@ let setup_daemon logger =
block_production_key
in
let block_production_pubkey =
maybe_from_config json_to_publickey_compressed_option
maybe_from_config
(json_to_publickey_compressed_option "block producer")
"block-producer-pubkey" block_production_pubkey
in
let block_production_password =
Expand All @@ -718,15 +718,15 @@ let setup_daemon logger =
let%bind block_production_keypair =
match (block_production_key, block_production_pubkey) with
| Some _, Some _ ->
eprintf
"Error: You cannot provide both `block-producer-key` and \
`block_production_pubkey`\n" ;
exit 11
Mina_user_error.raise
"You cannot provide both `block-producer-key` and \
`block_production_pubkey`"
| None, None ->
Deferred.return None
| Some sk_file, _ ->
let%map kp =
Secrets.Keypair.Terminal_stdin.read_from_env_exn sk_file
Secrets.Keypair.Terminal_stdin.read_from_env_exn
~which:"block producer keypair" sk_file
in
Some kp
| _, Some tracked_pubkey ->
Expand All @@ -736,7 +736,8 @@ let setup_daemon logger =
in
let sk_file = Secrets.Wallets.get_path wallets tracked_pubkey in
let%map kp =
Secrets.Keypair.Terminal_stdin.read_from_env_exn sk_file
Secrets.Keypair.Terminal_stdin.read_from_env_exn
~which:"block producer keypair" sk_file
in
Some kp
in
Expand All @@ -750,7 +751,15 @@ let setup_daemon logger =
match Unix.getenv "CODA_CLIENT_TRUSTLIST" with
| Some envstr ->
let cidrs =
String.split ~on:',' envstr |> List.map ~f:Unix.Cidr.of_string
String.split ~on:',' envstr
|> List.filter_map ~f:(fun str ->
try Some (Unix.Cidr.of_string str)
with _ ->
[%log warn]
"Could not parse address $address in \
CODA_CLIENT_TRUSTLIST"
~metadata:[("address", `String str)] ;
None )
in
Some
(List.append cidrs (Option.value ~default:[] client_trustlist))
Expand Down Expand Up @@ -833,13 +842,13 @@ let setup_daemon logger =
|> List.filter ~f:(fun s -> not (String.is_empty s))
|> List.map ~f:Coda_net2.Multiaddr.of_string
|> return
| Error e ->
[%log fatal]
~metadata:[("error", `String (Error.to_string_mach e))]
"Unable to read peer-list file properly. It must be a \
newline separated series of libp2p multiaddrs (ex: \
/ip4/IPADDR/tcp/PORT/p2p/PEERID)" ;
exit 15 )
| Error _ ->
Mina_user_error.raisef
~where:"reading libp2p peer address file"
"The file %s could not be read.\n\n\
It must be a newline-separated list of libp2p multiaddrs \
(ex: /ip4/IPADDR/tcp/PORT/p2p/PEERID)"
file )
in
let initial_peers =
List.concat
Expand Down
12 changes: 9 additions & 3 deletions src/app/cli/src/init/client.ml
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,9 @@ let batch_send_payments =
in
let main port (privkey_path, payments_path) =
let open Deferred.Let_syntax in
let%bind keypair = Secrets.Keypair.Terminal_stdin.read_exn privkey_path
let%bind keypair =
Secrets.Keypair.Terminal_stdin.read_exn ~which:"coda keypair"
privkey_path
and infos = get_infos payments_path in
let ts : User_command_input.t list =
List.map infos ~f:(fun {receiver; valid_until; amount; fee} ->
Expand Down Expand Up @@ -855,7 +857,10 @@ let dump_keypair =
Cli_lib.Exceptions.handle_nicely
@@ fun () ->
let open Deferred.Let_syntax in
let%map kp = Secrets.Keypair.Terminal_stdin.read_exn privkey_path in
let%map kp =
Secrets.Keypair.Terminal_stdin.read_exn ~which:"coda keypair"
privkey_path
in
printf "Public key: %s\nPrivate key: %s\n"
( kp.public_key |> Public_key.compress
|> Public_key.Compressed.to_base58_check )
Expand Down Expand Up @@ -1153,7 +1158,8 @@ let import_key =
in
let wallets_disk_location = conf_dir ^/ "wallets" in
let%bind ({Keypair.public_key; _} as keypair) =
Secrets.Keypair.Terminal_stdin.read_exn privkey_path
Secrets.Keypair.Terminal_stdin.read_exn ~which:"coda keypair"
privkey_path
in
let pk = Public_key.compress public_key in
let%bind wallets =
Expand Down
3 changes: 1 addition & 2 deletions src/app/rosetta/lib/signer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ module Keys = struct

let of_private_key_box secret_box_string =
let json = Yojson.Safe.from_string secret_box_string in
let which = Secrets.Keypair.T.which in
let sb : Secrets.Secret_box.t =
Secrets.Secret_box.of_yojson json |> Result.ok |> Option.value_exn
in
let output : Bytes.t =
Secrets.Secret_box.decrypt ~password:(Bytes.of_string "") ~which sb
Secrets.Secret_box.decrypt ~password:(Bytes.of_string "") sb
|> Result.ok |> Option.value_exn
in
let sk = output |> Bigstring.of_bytes |> Private_key.of_bigstring_exn in
Expand Down
9 changes: 6 additions & 3 deletions src/lib/genesis_ledger_helper/genesis_ledger_helper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1390,9 +1390,12 @@ let upgrade_old_config ~logger filename json =
`Assoc (("daemon", `Assoc old_fields) :: remaining_fields)
in
let%map () =
Writer.with_file filename ~f:(fun w ->
Deferred.return
@@ Writer.write w (Yojson.Safe.pretty_to_string upgraded_json) )
Deferred.Or_error.try_with (fun () ->
Writer.with_file filename ~f:(fun w ->
Deferred.return
@@ Writer.write w
(Yojson.Safe.pretty_to_string upgraded_json) ) )
|> Deferred.ignore_m
in
upgraded_json )
| _ ->
Expand Down
26 changes: 26 additions & 0 deletions src/lib/mina_user_error/mina_user_error.ml
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
exception Mina_user_error of {message: string; where: string option}

let raisef ?where =
Format.ksprintf (fun message -> raise (Mina_user_error {message; where}))

let raise ?where message = raise (Mina_user_error {message; where})

let () =
Stdlib.Printexc.register_printer (fun exn ->
match exn with
| Mina_user_error {message; where} ->
let error =
match where with
| None ->
"encountered a configuration error"
| Some where ->
Printf.sprintf "encountered a configuration error %s" where
in
Some
(Printf.sprintf {err|
FATAL ERROR

☠ Coda %s.

%s
%!|err}
error message)
| _ ->
None )
2 changes: 1 addition & 1 deletion src/lib/secrets/dune
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
(library_flags -linkall)
(inline_tests)
(libraries core async_unix sodium ppx_deriving_yojson.runtime yojson
coda_base coda_net2)
coda_base coda_net2 mina_user_error)
(preprocess
(pps ppx_coda ppx_version ppx_jane ppx_deriving_yojson ppx_deriving.make))
(instrumentation (backend bisect_ppx))
Expand Down
10 changes: 4 additions & 6 deletions src/lib/secrets/keypair.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ module T = struct
in
match%bind
Secret_file.write ~path:privkey_path ~mkdir:true ~plaintext:privkey_bytes
~password ~which
~password
with
| Ok () ->
(* The hope is that if [Secret_file.write] succeeded then this ought to
Expand All @@ -33,13 +33,13 @@ module T = struct
Writer.write_line pubkey_f pubkey_string ;
Writer.close pubkey_f
| Error e ->
Privkey_error.raise e
Privkey_error.raise ~which e

(** Reads a private key from [privkey_path] using [Secret_file] *)
let read ~(privkey_path : string) ~(password : Secret_file.password) :
(Keypair.t, Privkey_error.t) Deferred.Result.t =
let open Deferred.Result.Let_syntax in
let%bind pk_bytes = Secret_file.read ~path:privkey_path ~password ~which in
let%bind pk_bytes = Secret_file.read ~path:privkey_path ~password in
let open Result.Let_syntax in
Deferred.return
@@ let%bind sk =
Expand All @@ -50,7 +50,6 @@ module T = struct
Privkey_error.corrupted_privkey
(Error.createf "Error parsing decrypted private key file: %s"
(Exn.to_string exn))
which
in
try return (Keypair.of_private_key_exn sk)
with exn ->
Expand All @@ -59,7 +58,6 @@ module T = struct
"Error computing public key from private, is your keyfile \
corrupt? %s"
(Exn.to_string exn))
which

(** Reads a private key from [privkey_path] using [Secret_file], throws on failure *)
let read_exn ~(privkey_path : string) ~(password : Secret_file.password) :
Expand All @@ -68,7 +66,7 @@ module T = struct
| Ok keypair ->
keypair
| Error priv_key_error ->
Privkey_error.raise priv_key_error
Privkey_error.raise ~which priv_key_error

let read_exn' path =
read_exn ~privkey_path:path
Expand Down
16 changes: 9 additions & 7 deletions src/lib/secrets/keypair_common.ml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct
prompt_password prompt )
else return pw2

let read_exn ?(should_reask = true) path =
let read_exn ?(should_reask = true) ~which path =
let read_privkey password = read ~privkey_path:path ~password in
let%bind result =
match Sys.getenv env with
Expand All @@ -44,7 +44,9 @@ struct
| None ->
let read_file () =
read_privkey
(lazy (Password.read_hidden_line "Secret key password: "))
( lazy
(Password.read_hidden_line ~error_help_message:""
"Secret key password: ") )
in
let rec read_until_correct () =
match%bind read_file () with
Expand All @@ -54,30 +56,30 @@ struct
eprintf "Wrong password! Please try again\n" ;
read_until_correct ()
| Error exn ->
Privkey_error.raise exn
Deferred.Result.fail exn
in
if should_reask then read_until_correct () else read_file ()
in
match result with
| Ok result ->
return result
| Error e ->
Privkey_error.raise e
Privkey_error.raise ~which e

let read_from_env_exn path =
let read_from_env_exn ~which path =
let read_privkey password = read ~privkey_path:path ~password in
let%bind result =
match Sys.getenv env with
| Some password ->
read_privkey (lazy (Deferred.return @@ Bytes.of_string password))
| None ->
Privkey_error.raise (`Password_not_in_environment env)
Deferred.Result.fail (`Password_not_in_environment env)
in
match result with
| Ok result ->
return result
| Error e ->
Privkey_error.raise e
Privkey_error.raise ~which e

let write_exn kp ~privkey_path =
write_exn kp ~privkey_path
Expand Down
10 changes: 5 additions & 5 deletions src/lib/secrets/libp2p_keypair.ml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module T = struct
let str = Coda_net2.Keypair.to_string kp in
match%bind
Secret_file.write ~path:privkey_path ~mkdir:true
~plaintext:(Bytes.of_string str) ~password ~which
~plaintext:(Bytes.of_string str) ~password
with
| Ok () ->
(* The hope is that if [Secret_file.write] succeeded then this ought to
Expand All @@ -27,20 +27,20 @@ module T = struct
Writer.write_line pubkey_f (Coda_net2.Keypair.to_peer_id kp) ;
Writer.close pubkey_f
| Error e ->
Privkey_error.raise e
Privkey_error.raise ~which e

(** Reads a private key from [privkey_path] using [Secret_file] *)
let read ~(privkey_path : string) ~(password : Secret_file.password) :
(t, Privkey_error.t) Deferred.Result.t =
let open Deferred.Result.Let_syntax in
let%bind bytes = Secret_file.read ~path:privkey_path ~password ~which in
let%bind bytes = Secret_file.read ~path:privkey_path ~password in
Deferred.return
@@
match Coda_net2.Keypair.of_string (Bytes.to_string bytes) with
| Ok kp ->
Ok kp
| Error e ->
Privkey_error.corrupted_privkey e which
Privkey_error.corrupted_privkey e

(** Reads a private key from [privkey_path] using [Secret_file], throws on failure *)
let read_exn ~(privkey_path : string) ~(password : Secret_file.password) :
Expand All @@ -49,7 +49,7 @@ module T = struct
| Ok keypair ->
keypair
| Error priv_key_error ->
Privkey_error.raise priv_key_error
Privkey_error.raise ~which priv_key_error

let read_exn' path =
read_exn ~privkey_path:path
Expand Down
Loading