From cca19a04212866f128900c1ee62248a884b9ac2b Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Tue, 6 May 2025 11:25:05 +0200 Subject: [PATCH] Baker: move [check_dal_node] in agnostic library --- manifest/product_octez.ml | 1 + opam/octez-baker-lib.opam | 1 + src/lib_agnostic_baker/command_run.ml | 38 ++++++++++++++ src/lib_agnostic_baker/dune | 3 +- src/lib_agnostic_baker/errors.ml | 31 ++++++++++- src/lib_agnostic_baker/events.ml | 52 +++++++++++++++++++ src/lib_agnostic_baker/rpc_services.ml | 8 +++ src/lib_agnostic_baker/rpc_services.mli | 5 ++ .../lib_delegate/baking_commands.ml | 38 +------------- src/proto_alpha/lib_delegate/baking_errors.ml | 33 ------------ 10 files changed, 138 insertions(+), 72 deletions(-) diff --git a/manifest/product_octez.ml b/manifest/product_octez.ml index f3758bf27849..f36da707babb 100644 --- a/manifest/product_octez.ml +++ b/manifest/product_octez.ml @@ -5690,6 +5690,7 @@ let octez_agnostic_baker_lib = octez_profiler |> open_; octez_stdlib_unix |> open_; octez_shell_services |> open_; + octez_dal_node_services; ] (* PROTOCOL PACKAGES *) diff --git a/opam/octez-baker-lib.opam b/opam/octez-baker-lib.opam index cc65dc7a4c24..e79ff97035f7 100644 --- a/opam/octez-baker-lib.opam +++ b/opam/octez-baker-lib.opam @@ -14,6 +14,7 @@ depends: [ "bls12-381" { = version } "octez-shell-libs" { = version } "octez-node-config" { = version } + "tezos-dal-node-services" { = version } ] build: [ ["rm" "-r" "vendors" "contrib"] diff --git a/src/lib_agnostic_baker/command_run.ml b/src/lib_agnostic_baker/command_run.ml index eada3c274a19..de9c6bcb8b20 100644 --- a/src/lib_agnostic_baker/command_run.ml +++ b/src/lib_agnostic_baker/command_run.ml @@ -94,3 +94,41 @@ let check_node_version cctxt bypass allowed = baker_version; baker_commit_info; }) + +(* This function checks that a DAL node endpoint was given, + and that the specified DAL node is "healthy", + (the DAL's nodes 'health' RPC is used for that). *) +let check_dal_node = + let last_check_successful = ref false in + fun without_dal dal_node_rpc_ctxt -> + let open Lwt_result_syntax in + let result_emit f x = + let*! () = Events.emit f x in + return_unit + in + match (dal_node_rpc_ctxt, without_dal) with + | None, true -> + (* The user is aware that no DAL node is running, since they explicitly + used the [--without-dal] option. However, we do not want to reduce the + exposition of bakers to warnings about DAL, so we keep it. *) + result_emit Events.Commands.no_dal_node_provided () + | None, false -> tzfail No_dal_node_endpoint + | Some _, true -> tzfail Incompatible_dal_options + | Some ctxt, false -> ( + let*! health = Rpc_services.get_dal_health ctxt in + match health with + | Ok health -> ( + match health.status with + | Tezos_dal_node_services.Types.Health.Up -> + if !last_check_successful then return_unit + else ( + last_check_successful := true ; + result_emit Events.Commands.healthy_dal_node ()) + | _ -> + last_check_successful := false ; + result_emit + Events.Commands.unhealthy_dal_node + (ctxt#base, health)) + | Error _ -> + last_check_successful := false ; + result_emit Events.Commands.unreachable_dal_node ctxt#base) diff --git a/src/lib_agnostic_baker/dune b/src/lib_agnostic_baker/dune index 71c5978e6781..01c216674a4d 100644 --- a/src/lib_agnostic_baker/dune +++ b/src/lib_agnostic_baker/dune @@ -15,7 +15,8 @@ octez-shell-libs.client-commands octez-libs.octez-profiler octez-libs.stdlib-unix - octez-shell-libs.shell-services) + octez-shell-libs.shell-services + tezos-dal-node-services) (preprocess (pps octez-libs.ppx_profiler)) (preprocessor_deps (env_var TEZOS_PPX_PROFILER)) (flags diff --git a/src/lib_agnostic_baker/errors.ml b/src/lib_agnostic_baker/errors.ml index af4b8b99e1ab..9011d8932161 100644 --- a/src/lib_agnostic_baker/errors.ml +++ b/src/lib_agnostic_baker/errors.ml @@ -24,6 +24,8 @@ type error += | Block_vote_file_wrong_content of string | Block_vote_file_missing_liquidity_baking_toggle_vote of string | Missing_vote_on_startup + | No_dal_node_endpoint + | Incompatible_dal_options let () = Error_monad.register_error_kind @@ -252,4 +254,31 @@ let () = current working directory or in the baker directory.") Data_encoding.empty (function Missing_vote_on_startup -> Some () | _ -> None) - (fun () -> Missing_vote_on_startup) + (fun () -> Missing_vote_on_startup) ; + register_error_kind + `Permanent + ~id:"Client_commands.no_dal_node_endpoint" + ~title:"Missing_dal_node_argument" + ~description:"Explicit DAL node configuration is required." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "Please connect a running DAL node using '--dal-node '. If \ + you do not want to run a DAL node, you have to opt-out using \ + '--without-dal'.") + Data_encoding.unit + (function No_dal_node_endpoint -> Some () | _ -> None) + (fun () -> No_dal_node_endpoint) ; + register_error_kind + `Permanent + ~id:"Client_commands.incompatible_dal_options" + ~title:"Incompatible_dal_options" + ~description:"'--dal-node' and '--without-dal' are incompatible." + ~pp:(fun ppf () -> + Format.fprintf + ppf + "'--dal-node ' and '--without-dal' are incompatible. Please \ + do not pass '--without-dal' option.") + Data_encoding.unit + (function Incompatible_dal_options -> Some () | _ -> None) + (fun () -> Incompatible_dal_options) diff --git a/src/lib_agnostic_baker/events.ml b/src/lib_agnostic_baker/events.ml index 561301f828b6..d86c1d31d41e 100644 --- a/src/lib_agnostic_baker/events.ml +++ b/src/lib_agnostic_baker/events.ml @@ -189,3 +189,55 @@ module Per_block_votes = struct ~msg:"read adaptive issuance vote = {value}" ("value", Per_block_votes.adaptive_issuance_vote_encoding) end + +module Commands = struct + include Internal_event.Simple + + let section = section @ ["commands"] + + let no_dal_node_provided = + declare_0 + ~section + ~name:"no_dal_node_provided" + ~level:Warning + ~msg: + "No DAL node endpoint has been provided.\n\ + Not running a DAL node might result in losing a share of the \ + participation rewards.\n\ + For instructions on how to run a DAL node, please visit \ + https://docs.tezos.com/tutorials/join-dal-baker." + () + + let healthy_dal_node = + declare_0 + ~section + ~name:"healthy_dal_node" + ~level:Notice + ~msg:"The DAL node is healthy." + () + + let unhealthy_dal_node = + declare_2 + ~section + ~name:"unhealthy_dal_node" + ~level:Error + ~msg: + "The DAL node running on {endpoint} is not healthy. DAL attestations \ + cannot be sent. Its health is {health}. Please check that your DAL \ + node is configured correctly." + ~pp1:Uri.pp + ("endpoint", Tezos_rpc.Encoding.uri_encoding) + ~pp2:Tezos_dal_node_services.Types.Health.pp + ("health", Tezos_dal_node_services.Types.Health.encoding) + + let unreachable_dal_node = + declare_1 + ~section + ~name:"unreachable_dal_node" + ~level:Error + ~msg: + "The DAL node cannot be reached on endpoint: {endpoint}.\n\ + Please check your DAL node and possibly restart it." + ~pp1:Uri.pp + ("endpoint", Tezos_rpc.Encoding.uri_encoding) +end diff --git a/src/lib_agnostic_baker/rpc_services.ml b/src/lib_agnostic_baker/rpc_services.ml index b246f07ff106..6022775b97e2 100644 --- a/src/lib_agnostic_baker/rpc_services.ml +++ b/src/lib_agnostic_baker/rpc_services.ml @@ -103,3 +103,11 @@ let get_current_period ~node_addr = let* kind = get_string_field ~name:"kind" voting_period in let+ remaining = get_int_field ~name:"remaining" json in (kind, remaining)) + +let get_dal_health dal_node_rpc_ctxt = + Tezos_rpc.Context.make_call + Tezos_dal_node_services.Services.health + dal_node_rpc_ctxt + () + () + () diff --git a/src/lib_agnostic_baker/rpc_services.mli b/src/lib_agnostic_baker/rpc_services.mli index b8e1acb6a995..562de9f44e15 100644 --- a/src/lib_agnostic_baker/rpc_services.mli +++ b/src/lib_agnostic_baker/rpc_services.mli @@ -33,3 +33,8 @@ val get_next_protocol_hash : node_addr:string -> Protocol_hash.t tzresult Lwt.t - [remaining] is the number of blocks remaining until the end of the voting period. *) val get_current_period : node_addr:string -> (string * int) tzresult Lwt.t + +(** [get_dal_health ctxt] calls the DAL node RPC 'GET /health' *) +val get_dal_health : + Tezos_rpc.Context.generic -> + Tezos_dal_node_services.Types.Health.t tzresult Lwt.t diff --git a/src/proto_alpha/lib_delegate/baking_commands.ml b/src/proto_alpha/lib_delegate/baking_commands.ml index aeed25332883..482a35aaef6a 100644 --- a/src/proto_alpha/lib_delegate/baking_commands.ml +++ b/src/proto_alpha/lib_delegate/baking_commands.ml @@ -595,42 +595,6 @@ let remote_calls_timeout_arg = try return (Q.of_string s) with _ -> failwith "remote-calls-timeout expected int or float.")) -(* This function checks that a DAL node endpoint was given, - and that the specified DAL node is "healthy", - (the DAL's nodes 'health' RPC is used for that). *) -let check_dal_node = - let last_check_successful = ref false in - fun without_dal dal_node_rpc_ctxt -> - let open Lwt_result_syntax in - let result_emit f x = - let*! () = Events.emit f x in - return_unit - in - match (dal_node_rpc_ctxt, without_dal) with - | None, true -> - (* The user is aware that no DAL node is running, since they explicitly - used the [--without-dal] option. However, we do not want to reduce the - exposition of bakers to warnings about DAL, so we keep it. *) - result_emit Events.no_dal_node_provided () - | None, false -> tzfail No_dal_node_endpoint - | Some _, true -> tzfail Incompatible_dal_options - | Some ctxt, false -> ( - let*! health = Node_rpc.get_dal_health ctxt in - match health with - | Ok health -> ( - match health.status with - | Tezos_dal_node_services.Types.Health.Up -> - if !last_check_successful then return_unit - else ( - last_check_successful := true ; - result_emit Events.healthy_dal_node ()) - | _ -> - last_check_successful := false ; - result_emit Events.unhealthy_dal_node (ctxt#base, health)) - | Error _ -> - last_check_successful := false ; - result_emit Events.unreachable_dal_node ctxt#base) - type baking_mode = Local of {local_data_dir_path : string} | Remote let baker_args = @@ -731,7 +695,7 @@ let run_baker ?(recommend_agnostic_baker = true) let dal_node_rpc_ctxt = Option.map create_dal_node_rpc_ctxt dal_node_endpoint in - let* () = check_dal_node without_dal dal_node_rpc_ctxt in + let* () = Command_run.check_dal_node without_dal dal_node_rpc_ctxt in let* delegates = get_delegates cctxt sources in let context_path = match baking_mode with diff --git a/src/proto_alpha/lib_delegate/baking_errors.ml b/src/proto_alpha/lib_delegate/baking_errors.ml index b01327c556f4..9681072acfe9 100644 --- a/src/proto_alpha/lib_delegate/baking_errors.ml +++ b/src/proto_alpha/lib_delegate/baking_errors.ml @@ -320,39 +320,6 @@ let () = (fun (chain, block_hash, length) -> Unexpected_empty_block_list {chain; block_hash; length}) -(* DAL node related errors *) - -type error += No_dal_node_endpoint | Incompatible_dal_options - -let () = - register_error_kind - `Permanent - ~id:"Client_commands.no_dal_node_endpoint" - ~title:"Missing_dal_node_argument" - ~description:"Explicit DAL node configuration is required." - ~pp:(fun ppf () -> - Format.fprintf - ppf - "Please connect a running DAL node using '--dal-node '. If \ - you do not want to run a DAL node, you have to opt-out using \ - '--without-dal'.") - Data_encoding.unit - (function No_dal_node_endpoint -> Some () | _ -> None) - (fun () -> No_dal_node_endpoint) ; - register_error_kind - `Permanent - ~id:"Client_commands.incompatible_dal_options" - ~title:"Incompatible_dal_options" - ~description:"'--dal-node' and '--without-dal' are incompatible." - ~pp:(fun ppf () -> - Format.fprintf - ppf - "'--dal-node ' and '--without-dal' are incompatible. Please \ - do not pass '--without-dal' option.") - Data_encoding.unit - (function Incompatible_dal_options -> Some () | _ -> None) - (fun () -> Incompatible_dal_options) - (* BLS related errors *) type error += | Signature_aggregation_failure -- GitLab