diff --git a/.dockerignore b/.dockerignore index 72b2fdad3a6a36fd55f392e07df765c0f6477335..2cff9fde47779888ee9fef9fd83283373554fcad 100644 --- a/.dockerignore +++ b/.dockerignore @@ -39,6 +39,7 @@ octez-injector-server octogram octez-teztale-archiver octez-teztale-server +octez-accuser octez-agnostic-baker scripts/opam-test-all.sh.DONE diff --git a/.gitignore b/.gitignore index 00c5639a874fd5fae0409e0aa8477e10c9295a14..3a73a1745e6726b5dfe45a7d28c57bad3d4884cf 100644 --- a/.gitignore +++ b/.gitignore @@ -62,6 +62,7 @@ __pycache__ /safety-checker /octez-teztale-archiver /octez-teztale-server +/octez-accuser /octez-agnostic-baker /octez-teztale-snitch diff --git a/.gitlab/ci/pipelines/schedule_extended_test.yml b/.gitlab/ci/pipelines/schedule_extended_test.yml index 8d6a7bfd9127e1e62f3009a25be77f30fe78a540..9f3b5757af547b75c1ed035dfbbe899035411c9c 100644 --- a/.gitlab/ci/pipelines/schedule_extended_test.yml +++ b/.gitlab/ci/pipelines/schedule_extended_test.yml @@ -1207,6 +1207,7 @@ opam:all_6: - tezt-tezos - tezos-protocol-genesis - tezos-protocol-demo-noops + - tezos-protocol-demo-counter - tezos-openapi - tezos-dal-node-services - tezos-benchmark @@ -1214,7 +1215,6 @@ opam:all_6: - octez-riscv-pvm - octez-proto-libs - octez-performance-metrics - - octez-libs - octez-l2-libs - efunc_core - dal_node_migrations @@ -1332,6 +1332,7 @@ opam:all_2: - octez-smart-rollup-node-lib - octez-smart-rollup-node-alpha - octez-smart-rollup-node-PtParisB + - octez-smart-rollup-node-PtNairob - octez-protocol-alpha-libs - octez-protocol-022-PsRiotum-libs - octez-protocol-021-PsQuebec-libs @@ -1340,7 +1341,6 @@ opam:all_2: - octez-protocol-018-Proxford-libs - octez-protocol-017-PtNairob-libs - octez-protocol-016-PtMumbai-libs - - octez-protocol-001-PtCJ7pwo-libs - octez-protocol-000-Ps9mPmXa-libs - octez-injector - octez-agnostic-baker-lib @@ -1398,7 +1398,6 @@ opam:all_1: parallel: matrix: - package: - - octez-smart-rollup-node-PtNairob - octez-smart-rollup-node-PsRiotum - octez-smart-rollup-node-PsQuebec - octez-smart-rollup-node-PsParisC @@ -1457,7 +1456,6 @@ opam:all_3: parallel: matrix: - package: - - tezos-client-demo-counter - octez-rpc-process - octez-protocol-015-PtLimaPt-libs - octez-protocol-014-PtKathma-libs @@ -1473,6 +1471,7 @@ opam:all_3: - octez-protocol-004-Pt24m4xi-libs - octez-protocol-003-PsddFKi3-libs - octez-protocol-002-PsYLVpVv-libs + - octez-protocol-001-PtCJ7pwo-libs opam:exec_4: image: ${ci_image_name}/prebuild:${ci_image_tag} @@ -1582,7 +1581,6 @@ opam:all_4: parallel: matrix: - package: - - tezos-protocol-008-PtEdoTez - tezos-protocol-008-PtEdo2Zk - tezos-protocol-007-PsDELPH1 - tezos-protocol-006-PsCARTHA @@ -1595,6 +1593,7 @@ opam:all_4: - tezos-protocol-000-Ps9mPmXa - tezos-dal-node-lib - tezos-client-genesis + - tezos-client-demo-counter - octez-node-config - octez-crawler @@ -1662,6 +1661,7 @@ opam:exec_1: - octez-agnostic-baker - octez-accuser-PsRiotum - octez-accuser-PsQuebec + - octez-accuser opam:all_5: image: ${ci_image_name}/prebuild:${ci_image_tag} @@ -1716,7 +1716,6 @@ opam:all_5: parallel: matrix: - package: - - tezos-protocol-demo-counter - tezos-protocol-alpha - tezos-protocol-022-PsRiotum - tezos-protocol-021-PsQuebec @@ -1732,6 +1731,7 @@ opam:all_5: - tezos-protocol-011-PtHangz2 - tezos-protocol-010-PtGRANAD - tezos-protocol-009-PsFLoren + - tezos-protocol-008-PtEdoTez opam:all_7: image: ${ci_image_name}/prebuild:${ci_image_tag} @@ -1791,6 +1791,7 @@ opam:all_7: - octez-rust-deps - octez-riscv-api - octez-protocol-compiler-compat + - octez-libs - octez-internal-libs - octez-distributed-lwt-internal - octez-distributed-internal diff --git a/dune-project b/dune-project index 0ad15e5884df5e4b3fc541cf598594dfa2b183f2..14be4e75eed3febd8f917c075991c3ffcbeaf926 100644 --- a/dune-project +++ b/dune-project @@ -16,6 +16,7 @@ (package (name internal-devtools_proto-context-du)) (package (name kaitai)) (package (name kaitai-of-data-encoding)) +(package (name octez-accuser)) (package (name octez-accuser-PsQuebec)) (package (name octez-accuser-PsRiotum)) (package (name octez-accuser-alpha)) diff --git a/manifest/product_octez.ml b/manifest/product_octez.ml index 2ded41146a4db0a22d4b72ed907213f51c8034fd..084feef784f6a197dd6ed38744b7d62dc6042371 100644 --- a/manifest/product_octez.ml +++ b/manifest/product_octez.ml @@ -8600,6 +8600,40 @@ let _octez_agnostic_baker = @ protocol_deps) ~linkall:true +let _octez_agnostic_accuser = + let (PPX {preprocess; preprocessor_deps}) = ppx_profiler in + let protocol_deps = + let deps_for_protocol protocol = + let is_optional = + match (Protocol.status protocol, Protocol.number protocol) with + | Active, V _ -> false + | (Frozen | Overridden | Not_mainnet), _ | Active, (Dev | Other) -> true + in + let targets = List.filter_map Fun.id [Protocol.agnostic_baker protocol] in + if is_optional then List.map optional targets else targets + in + List.map deps_for_protocol Protocol.all |> List.flatten + in + public_exe + "octez-accuser" + ~path:"src/bin_agnostic_accuser" + ~internal_name:"main_agnostic_accuser" + ~synopsis:"Tezos: `octez-accuser` binary for denunciation" + ~preprocess + ~preprocessor_deps + ~release_status:Released + ~with_macos_security_framework:true + ~deps: + ([ + bls12_381_archive; + octez_base |> open_ ~m:"TzPervasives" |> open_; + octez_base_unix |> open_; + octez_client_base_unix |> open_; + octez_agnostic_baker_lib |> open_; + ] + @ protocol_deps) + ~linkall:true + let _octez_client = let protocol_deps = let deps_for_protocol protocol = diff --git a/opam/octez-accuser.opam b/opam/octez-accuser.opam new file mode 100644 index 0000000000000000000000000000000000000000..1d76174cbc5f1a98d852281881a4bc456b7bf7ce --- /dev/null +++ b/opam/octez-accuser.opam @@ -0,0 +1,33 @@ +# This file was automatically generated, do not edit. +# Edit file manifest/main.ml instead. +opam-version: "2.0" +maintainer: "contact@tezos.com" +authors: ["Tezos devteam"] +homepage: "https://www.tezos.com/" +bug-reports: "https://gitlab.com/tezos/tezos/issues" +dev-repo: "git+https://gitlab.com/tezos/tezos.git" +license: "MIT" +depends: [ + "dune" { >= "3.11.1" } + "ocaml" { >= "4.14" } + "octez-libs" { = version } + "octez-rust-deps" { = version } + "bls12-381" { = version } + "octez-shell-libs" { = version } + "octez-agnostic-baker-lib" { = version } + "octez-protocol-021-PsQuebec-libs" { = version } + "octez-protocol-022-PsRiotum-libs" { = version } +] +depopts: [ + "octez-protocol-alpha-libs" +] +conflicts: [ + "octez-protocol-alpha-libs" { != version } +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +available: os-family != "windows" +synopsis: "Tezos: `octez-accuser` binary for denunciation" diff --git a/script-inputs/ci-opam-package-tests b/script-inputs/ci-opam-package-tests index 82c6e6d298902277737f4019a802e48dc3fd0665..011603ddce7d4a55090d0e66691808111b51a022 100644 --- a/script-inputs/ci-opam-package-tests +++ b/script-inputs/ci-opam-package-tests @@ -1,6 +1,7 @@ bls12-381 all 7 dal_node_migrations all 6 efunc_core all 6 +octez-accuser exec 1 octez-accuser-PsQuebec exec 1 octez-accuser-PsRiotum exec 1 octez-agnostic-baker exec 1 @@ -17,13 +18,13 @@ octez-distributed-lwt-internal all 7 octez-injector all 2 octez-internal-libs all 7 octez-l2-libs all 6 -octez-libs all 6 +octez-libs all 7 octez-node exec 1 octez-node-config all 4 octez-performance-metrics all 6 octez-proto-libs all 6 octez-protocol-000-Ps9mPmXa-libs all 2 -octez-protocol-001-PtCJ7pwo-libs all 2 +octez-protocol-001-PtCJ7pwo-libs all 3 octez-protocol-002-PsYLVpVv-libs all 3 octez-protocol-003-PsddFKi3-libs all 3 octez-protocol-004-Pt24m4xi-libs all 3 @@ -60,7 +61,7 @@ octez-smart-rollup-node-Proxford all 1 octez-smart-rollup-node-PsParisC all 1 octez-smart-rollup-node-PsQuebec all 1 octez-smart-rollup-node-PsRiotum all 1 -octez-smart-rollup-node-PtNairob all 1 +octez-smart-rollup-node-PtNairob all 2 octez-smart-rollup-node-PtParisB all 2 octez-smart-rollup-node-alpha all 2 octez-smart-rollup-node-lib all 2 @@ -69,7 +70,7 @@ octez-smart-rollup-wasm-debugger-lib all 2 octez-smart-rollup-wasm-debugger-plugin all 7 octez-version exec 6 tezos-benchmark all 6 -tezos-client-demo-counter all 3 +tezos-client-demo-counter all 4 tezos-client-genesis all 4 tezos-dal-node-lib all 4 tezos-dal-node-services all 6 @@ -84,7 +85,7 @@ tezos-protocol-005-PsBabyM1 all 4 tezos-protocol-006-PsCARTHA all 4 tezos-protocol-007-PsDELPH1 all 4 tezos-protocol-008-PtEdo2Zk all 4 -tezos-protocol-008-PtEdoTez all 4 +tezos-protocol-008-PtEdoTez all 5 tezos-protocol-009-PsFLoren all 5 tezos-protocol-010-PtGRANAD all 5 tezos-protocol-011-PtHangz2 all 5 @@ -100,7 +101,7 @@ tezos-protocol-020-PsParisC all 5 tezos-protocol-021-PsQuebec all 5 tezos-protocol-022-PsRiotum all 5 tezos-protocol-alpha all 5 -tezos-protocol-demo-counter all 5 +tezos-protocol-demo-counter all 6 tezos-protocol-demo-noops all 6 tezos-protocol-genesis all 6 tezt-tezos all 6 diff --git a/script-inputs/octez-released-executables b/script-inputs/octez-released-executables index d13fa93a0bea62aa9abcef9ea9ac488004a84413..874050eb084e33831eccbd08414202ce5c582c5c 100644 --- a/script-inputs/octez-released-executables +++ b/script-inputs/octez-released-executables @@ -5,6 +5,7 @@ octez-signer octez-codec octez-client octez-admin-client +octez-accuser octez-agnostic-baker octez-node octez-accuser-PsRiotum diff --git a/script-inputs/released-executables b/script-inputs/released-executables index d13fa93a0bea62aa9abcef9ea9ac488004a84413..874050eb084e33831eccbd08414202ce5c582c5c 100644 --- a/script-inputs/released-executables +++ b/script-inputs/released-executables @@ -5,6 +5,7 @@ octez-signer octez-codec octez-client octez-admin-client +octez-accuser octez-agnostic-baker octez-node octez-accuser-PsRiotum diff --git a/src/bin_agnostic_accuser/dune b/src/bin_agnostic_accuser/dune new file mode 100644 index 0000000000000000000000000000000000000000..390efe12addf28e3024b1fa422c0c8740cff8179 --- /dev/null +++ b/src/bin_agnostic_accuser/dune @@ -0,0 +1,39 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(executable + (name main_agnostic_accuser) + (public_name octez-accuser) + (package octez-accuser) + (instrumentation (backend bisect_ppx)) + (libraries + octez-rust-deps + bls12-381.archive + octez-libs.base + octez-libs.base.unix + octez-shell-libs.client-base-unix + octez-agnostic-baker-lib + octez-protocol-021-PsQuebec-libs.agnostic-baker + octez-protocol-022-PsRiotum-libs.agnostic-baker + (select void_for_linking-octez-protocol-alpha-libs-agnostic-baker from + (octez-protocol-alpha-libs.agnostic-baker -> void_for_linking-octez-protocol-alpha-libs-agnostic-baker.empty) + (-> void_for_linking-octez-protocol-alpha-libs-agnostic-baker.empty))) + (preprocess (pps octez-libs.ppx_profiler)) + (preprocessor_deps (env_var TEZOS_PPX_PROFILER)) + (link_flags + (:standard) + (:include %{workspace_root}/static-link-flags.sexp) + (:include %{workspace_root}/macos-link-flags.sexp) + (-linkall)) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_base + -open Tezos_base_unix + -open Tezos_client_base_unix + -open Octez_agnostic_baker)) + +(rule + (action + (progn + (write-file void_for_linking-octez-protocol-alpha-libs-agnostic-baker.empty "")))) diff --git a/src/bin_agnostic_accuser/main_agnostic_accuser.ml b/src/bin_agnostic_accuser/main_agnostic_accuser.ml new file mode 100644 index 0000000000000000000000000000000000000000..dce135f196c6b2057be80fbb5fb1c50ff8d143e6 --- /dev/null +++ b/src/bin_agnostic_accuser/main_agnostic_accuser.ml @@ -0,0 +1,79 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2025 Trilitech *) +(* *) +(*****************************************************************************) + +(* Main entrypoint for the agnostic accuser binary. + + We distinguish two cases: + 1. If the binary is called against a `--help`, `--version` or `man` command, then + there is no reason to connect to a node, find the current protocol etc. + 2. Otherwise, we run the agnostic accuser daemon, which first obtains the + current protocol from the connected node, and then it monitors the chain + to determine when to switch to a new protocol accuser process. *) + +let[@warning "-32"] may_start_profiler baking_dir = + match Tezos_profiler_unix.Profiler_instance.selected_backend () with + | Some {instance_maker; _} -> + let profiler_maker = instance_maker ~directory:baking_dir in + Agnostic_baker_profiler.init profiler_maker + | None -> () + +let lwt_run ~args () = + let open Lwt_result_syntax in + let base_dir = + Option.value + ~default:Agnostic_baker_config.default_base_dir + (Run_args.get_base_dir args) + in + let*! () = + Client_main_run.init_logging (module Agnostic_baker_config) ~base_dir () + in + () [@profiler.overwrite may_start_profiler base_dir] ; + let daemon = + Daemon.Accuser.create + ~node_endpoint:(Run_args.get_endpoint args) + ~keep_alive:(Run_args.keep_alive args) + in + let* (_ : unit) = Daemon.Accuser.run daemon in + let*! () = Lwt_utils.never_ending () in + return_unit + +let run ~args () = + let open Lwt_syntax in + let main_promise = + Lwt.catch (lwt_run ~args) (function + | Failure msg -> failwith "%s" msg + | exn -> failwith "%s" (Printexc.to_string exn)) + in + Stdlib.exit + (Tezos_base_unix.Event_loop.main_run (fun () -> + let* retcode = + let* r = Lwt_exit.wrap_and_exit main_promise in + match r with + | Ok () -> Lwt.return 0 + | Error errs -> + Format.eprintf "%a" Error_monad.pp_print_trace errs ; + Lwt.return 1 + in + Format.pp_print_flush Format.err_formatter () ; + Format.pp_print_flush Format.std_formatter () ; + let* () = Tezos_base_unix.Internal_event_unix.close () in + return retcode)) + +let () = + let args = Array.to_list Sys.argv in + if + Run_args.( + only_exe args || is_help_cmd args || is_version_cmd args + || is_man_cmd args) + then + (* No need to run the accuser commands, we just need to get their description, + therefore we do not obtain the protocol plugin. *) + Client_main_run.run + (module Agnostic_baker_config) + ~select_commands:(fun _ _ -> + Lwt_result_syntax.return @@ Commands.accuser_commands ()) + else run ~args () diff --git a/src/bin_agnostic_baker/main_agnostic_baker.ml b/src/bin_agnostic_baker/main_agnostic_baker.ml index 2d7dc5c7aca16f95c9d3213cc3321749c5a14aba..f68b9a1de76e588fd66a075d45c98fe40570d45e 100644 --- a/src/bin_agnostic_baker/main_agnostic_baker.ml +++ b/src/bin_agnostic_baker/main_agnostic_baker.ml @@ -56,11 +56,11 @@ let lwt_run ~args () = in () [@profiler.overwrite may_start_profiler base_dir] ; let daemon = - Daemon.create + Daemon.Baker.create ~node_endpoint:(Run_args.get_endpoint args) ~keep_alive:(Run_args.keep_alive args) in - let* (_ : unit) = Daemon.run daemon in + let* (_ : unit) = Daemon.Baker.run daemon in let*! () = Lwt_utils.never_ending () in return_unit diff --git a/src/bin_client/octez-init-sandboxed-client.sh b/src/bin_client/octez-init-sandboxed-client.sh index c6347a35b16e7eb471fdeed4dfc0443c739a2a53..9d85de65d3b4d11bff114fc89d4ad2caabf1b153 100755 --- a/src/bin_client/octez-init-sandboxed-client.sh +++ b/src/bin_client/octez-init-sandboxed-client.sh @@ -132,6 +132,7 @@ main() { protocol_without_number=$(echo "$protocol" | tr -d "\-[0-9]") local_baker="$bin_dir/../../_build/default/src/proto_$protocol_underscore/bin_baker/main_baker_$protocol_underscore.exe" local_agnostic_baker="$bin_dir/../../_build/default/src/bin_agnostic_baker/main_agnostic_baker.exe" + local_agnostic_accuser="$bin_dir/../../_build/default/src/bin_agnostic_accuser/main_agnostic_accuser.exe" local_accuser="$bin_dir/../../_build/default/src/proto_$protocol_underscore/bin_accuser/main_accuser_$protocol_underscore.exe" local_sc_rollup_node="$bin_dir/../../_build/default/src/proto_$protocol_underscore/bin_sc_rollup_node/main_sc_rollup_node_$protocol_underscore.exe" parameters_file="$bin_dir/../../_build/default/src/proto_$protocol_underscore/lib_parameters/sandbox-parameters.json" @@ -145,6 +146,7 @@ main() { baker="$local_baker --base-dir $client_dir --endpoint $endpoint" agnostic_baker="$local_agnostic_baker --base-dir $client_dir --endpoint $endpoint" + agnostic_accuser="$local_agnostic_accuser --base-dir $client_dir --endpoint $endpoint" accuser="$local_accuser --base-dir $client_dir --endpoint $endpoint" sc_rollup_node="$local_sc_rollup_node --base-dir $client_dir --endpoint $endpoint" @@ -156,6 +158,10 @@ main() { echo "exec $agnostic_baker \"\$@\"" >> "$client_dir"/bin/octez-agnostic-baker chmod +x "$client_dir"/bin/octez-agnostic-baker + echo '#!/bin/sh' > "$client_dir"/bin/octez-accuser + echo "exec $agnostic_accuser \"\$@\"" >> "$client_dir"/bin/octez-accuser + chmod +x "$client_dir"/bin/octez-accuser + echo '#!/bin/sh' > "$client_dir"/bin/octez-smart-rollup-node-"$protocol_without_number" echo "exec $sc_rollup_node \"\$@\" --data-dir $rollup_node_dir" >> "$client_dir"/bin/octez-smart-rollup-node-"$protocol_without_number" chmod +x "$client_dir"/bin/octez-smart-rollup-node-"$protocol_without_number" diff --git a/src/lib_agnostic_baker/commands.ml b/src/lib_agnostic_baker/commands.ml index 3a5d1ccca9c7a53d711aa243fa876ccff9a670cd..dd77615027ad7608097a977b971c62ed28e8f734 100644 --- a/src/lib_agnostic_baker/commands.ml +++ b/src/lib_agnostic_baker/commands.ml @@ -82,3 +82,23 @@ let baker_commands ?plugin () = | Some plugin -> run_accuser plugin | None -> fun _ _ -> Lwt_result_syntax.return_unit); ] + +let accuser_commands ?plugin () = + let open Configuration in + let open Tezos_clic in + let group = + { + name = "delegate.accuser"; + title = "Commands related to the agnostic accuser daemon."; + } + in + [ + command + ~group + ~desc:"Launch the accuser daemon" + (args3 pidfile_arg preserved_levels_arg keep_alive_arg) + (prefix "run" @@ stop) + (match plugin with + | Some plugin -> run_accuser plugin + | None -> fun _ _ -> Lwt_result_syntax.return_unit); + ] diff --git a/src/lib_agnostic_baker/commands.mli b/src/lib_agnostic_baker/commands.mli index ded33916227ff76067d2afbc2922b80313fe8f8c..b4ea9bbb855a318eaa3450dbcb3bf074e753df08 100644 --- a/src/lib_agnostic_baker/commands.mli +++ b/src/lib_agnostic_baker/commands.mli @@ -16,3 +16,10 @@ val baker_commands : ?plugin:(module Protocol_plugin_sig.S) -> unit -> Tezos_client_base.Client_context.full Tezos_clic.command list + +(** [accuser_commands ?plugin ()] behaves similarly to [baker_commands], but + for the accuser process. *) +val accuser_commands : + ?plugin:(module Protocol_plugin_sig.S) -> + unit -> + Tezos_client_base.Client_context.full Tezos_clic.command list diff --git a/src/lib_agnostic_baker/daemon.ml b/src/lib_agnostic_baker/daemon.ml index fe004ef0c80f6158ada29726cc7b125a33b14453..f91f5bbc9f20e96263cf33ae77ae0232c966f5b4 100644 --- a/src/lib_agnostic_baker/daemon.ml +++ b/src/lib_agnostic_baker/daemon.ml @@ -6,8 +6,7 @@ (* *) (*****************************************************************************) -open Agnostic_baker_errors -module Events = Agnostic_baker_events +open Errors module Profiler = struct include (val Profiler.wrap Agnostic_baker_profiler.agnostic_baker_profiler) @@ -17,320 +16,384 @@ module Profiler = struct Agnostic_baker_profiler.agnostic_baker_profiler end -type process = {thread : int Lwt.t; canceller : int Lwt.u} - -type baker = {protocol_hash : Protocol_hash.t; process : process} - -type baker_to_kill = {baker : baker; level_to_kill : int} - -type state = { - node_endpoint : string; - mutable current_baker : baker option; - mutable old_baker : baker_to_kill option; - keep_alive : bool; -} - -type t = state - -(* ---- Baker Process Management ---- *) - -let rec retry_on_disconnection ~emit node_addr f = - let open Lwt_result_syntax in - let*! result = f () in - match result with - | Ok () -> return_unit - | Error (Lost_node_connection :: _ | Cannot_connect_to_node _ :: _) -> - let* _level = - Utils.retry - ~emit - ~max_delay:10. - ~delay:1. - ~factor:1.5 - ~tries:max_int - ~is_error:(function Cannot_connect_to_node _ -> true | _ -> false) - (fun node_addr -> Rpc_services.get_level ~node_addr) - node_addr - in - retry_on_disconnection ~emit node_addr f - | Error trace -> fail trace - -(** [run_thread ~protocol_hash ~baker_commands ~cancel_promise] - returns the main running thread for the baker given its protocol [~protocol_hash], - corresponding commands [~baker_commands] and cancellation [~cancel_promise]. *) -let run_thread ~protocol_hash ~baker_commands ~cancel_promise = - let () = - Client_commands.register protocol_hash @@ fun _network -> baker_commands - in - - (* This call is not strictly necessary as the parameters are initialized - lazily the first time a Sapling operation (validation or forging) is - done. This is what the client does. - For a long running binary however it is important to make sure that the - parameters files are there at the start and avoid failing much later while - validating an operation. Plus paying this cost upfront means that the first - validation will not be more expensive. *) - let () = Tezos_sapling.Core.Validator.init_params () in - - Lwt.pick - [ - Client_main_run.lwt_run - (module Agnostic_baker_config) - ~select_commands:(fun _ _ -> Lwt_result_syntax.return baker_commands) - (* The underlying logging from the baker must not be initialised, otherwise we double log. *) - ~disable_logging:true - (); - cancel_promise; - ] - -(** [spawn_baker protocol_hash] spawns a new baker process for the given [protocol_hash]. *) -let spawn_baker protocol_hash = - let open Lwt_result_syntax in - let*! () = Events.(emit starting_baker) protocol_hash in - let cancel_promise, canceller = Lwt.wait () in - let* thread = - let*? plugin = - (Protocol_plugins.proto_plugin_for_protocol - protocol_hash - [@profiler.record_f {verbosity = Notice} "proto_plugin_for_protocol"]) +module type AGNOSTIC_DAEMON = sig + type t + + val create : node_endpoint:string -> keep_alive:bool -> t + + val run : t -> unit tzresult Lwt.t +end + +module type AGENT = sig + val name : string + + val commands : + ?plugin:(module Protocol_plugin_sig.S) -> + unit -> + Tezos_client_base.Client_context.full Tezos_clic.command list + + val init_sapling_params : bool +end + +module Baker_agent : AGENT = struct + let name = "baker" + + let commands = Commands.baker_commands + + let init_sapling_params = true +end + +module Accuser_agent : AGENT = struct + let name = "accuser" + + let commands = Commands.accuser_commands + + let init_sapling_params = false +end + +module Make_daemon (Agent : AGENT) : AGNOSTIC_DAEMON = struct + type process = {thread : int Lwt.t; canceller : int Lwt.u} + + type baker = {protocol_hash : Protocol_hash.t; process : process} + + type baker_to_kill = {baker : baker; level_to_kill : int} + + type state = { + node_endpoint : string; + mutable current_baker : baker option; + mutable old_baker : baker_to_kill option; + keep_alive : bool; + } + + type t = state + + (* ---- Baker Process Management ---- *) + + let rec retry_on_disconnection ~emit node_addr f = + let open Lwt_result_syntax in + let*! result = f () in + match result with + | Ok () -> return_unit + | Error (Lost_node_connection :: _ | Cannot_connect_to_node _ :: _) -> + let* _level = + Utils.retry + ~emit + ~max_delay:10. + ~delay:1. + ~factor:1.5 + ~tries:max_int + ~is_error:(function Cannot_connect_to_node _ -> true | _ -> false) + (fun node_addr -> Rpc_services.get_level ~node_addr) + node_addr + in + retry_on_disconnection ~emit node_addr f + | Error trace -> fail trace + + (** [run_thread ~protocol_hash ~cancel_promise ~init_sapling_params] returns the main running thread + for the baker given its protocol [~protocol_hash] and cancellation [~cancel_promise]. It can + optionally initialise sapling parameters, as requested by [~init_sapling_params]. *) + let run_thread ~protocol_hash ~cancel_promise ~init_sapling_params = + let plugin = + match + Protocol_plugins.proto_plugin_for_protocol + protocol_hash + [@profiler.record_f {verbosity = Notice} "proto_plugin_for_protocol"] + with + | Error e -> + Format.kasprintf + Stdlib.failwith + "Cannot start %s for protocol %a.\n%a" + Agent.name + Protocol_hash.pp + protocol_hash + pp_print_trace + e + | Ok plugin -> plugin in - let baker_commands = Commands.baker_commands ~plugin () in - return @@ run_thread ~protocol_hash ~baker_commands ~cancel_promise - in - let*! () = Events.(emit baker_running) protocol_hash in - return {protocol_hash; process = {thread; canceller}} -(** [hot_swap_baker ~state ~current_protocol_hash ~next_protocol_hash + let () = + Client_commands.register protocol_hash @@ fun _network -> + Agent.commands ~plugin () + in + + if init_sapling_params then + (* This call is not strictly necessary as the parameters are initialized + lazily the first time a Sapling operation (validation or forging) is + done. This is what the client does. + For a long running binary however it is important to make sure that the + parameters files are there at the start and avoid failing much later while + validating an operation. Plus paying this cost upfront means that the first + validation will not be more expensive. *) + Tezos_sapling.Core.Validator.init_params () + else () ; + + Lwt.pick + [ + Client_main_run.lwt_run + (module Agnostic_baker_config) + ~select_commands:(fun _ _ -> + Lwt_result_syntax.return @@ Agent.commands ~plugin ()) + (* The underlying logging from the baker must not be initialised, otherwise we double log. *) + ~disable_logging:true + (); + cancel_promise; + ] + + (** [spawn_baker protocol_hash] spawns a new baker process for the given [protocol_hash]. *) + let spawn_baker protocol_hash = + let open Lwt_result_syntax in + let*! () = Events.(emit starting_agent) (Agent.name, protocol_hash) in + let cancel_promise, canceller = Lwt.wait () in + let thread = + run_thread + ~protocol_hash + ~cancel_promise + ~init_sapling_params:Agent.init_sapling_params + in + let*! () = Events.(emit agent_running) (Agent.name, protocol_hash) in + return {protocol_hash; process = {thread; canceller}} + + (** [hot_swap_baker ~state ~current_protocol_hash ~next_protocol_hash ~level_to_kill_old_baker] moves the current baker into the old baker slot (to be killed later) and spawns a new baker for [~next_protocol_hash] *) -let hot_swap_baker ~state ~current_protocol_hash ~next_protocol_hash - ~level_to_kill_old_baker = - let open Lwt_result_syntax in - let* current_baker = - match state.current_baker with - | Some baker -> return baker - | None -> tzfail Missing_current_baker - in - let next_proto_status = Parameters.protocol_status next_protocol_hash in - let*! () = - Events.(emit protocol_encountered) (next_proto_status, next_protocol_hash) - in - let*! () = - Events.(emit become_old_baker) - (current_protocol_hash, level_to_kill_old_baker) - in - state.old_baker <- - Some {baker = current_baker; level_to_kill = level_to_kill_old_baker} ; - state.current_baker <- None ; - let* new_baker = spawn_baker next_protocol_hash in - state.current_baker <- Some new_baker ; - return_unit - -(** [maybe_kill_old_baker state node_addr] checks whether the [old_baker] process + let hot_swap_baker ~state ~current_protocol_hash ~next_protocol_hash + ~level_to_kill_old_baker = + let open Lwt_result_syntax in + let* current_baker = + match state.current_baker with + | Some baker -> return baker + | None -> tzfail (Missing_current_agent Agent.name) + in + let next_proto_status = Parameters.protocol_status next_protocol_hash in + let*! () = + Events.(emit protocol_encountered) (next_proto_status, next_protocol_hash) + in + let*! () = + Events.(emit become_old_agent) + (Agent.name, current_protocol_hash, level_to_kill_old_baker) + in + state.old_baker <- + Some {baker = current_baker; level_to_kill = level_to_kill_old_baker} ; + state.current_baker <- None ; + let* new_baker = spawn_baker next_protocol_hash in + state.current_baker <- Some new_baker ; + return_unit + + (** [maybe_kill_old_baker state node_addr] checks whether the [old_baker] process from the [state] of the agnostic baker has surpassed its lifetime and it stops it if that is the case. *) -let maybe_kill_old_baker state node_addr = - let open Lwt_result_syntax in - match state.old_baker with - | None -> return_unit - | Some {baker; level_to_kill} -> - let* head_level = - (Rpc_services.get_level - ~node_addr [@profiler.record_s {verbosity = Notice} "get_level"]) - in - if head_level >= level_to_kill then ( - let*! () = Events.(emit stopping_baker) baker.protocol_hash in - Lwt.wakeup - baker.process.canceller - 0 [@profiler.record_f {verbosity = Notice} "kill old baker"] ; - state.old_baker <- None ; - return_unit) - else return_unit - -(* ---- Baker and Chain Monitoring ---- *) - -(** [monitor_heads ~node_addr] creates a stream which returns the data + let maybe_kill_old_baker state node_addr = + let open Lwt_result_syntax in + match state.old_baker with + | None -> return_unit + | Some {baker; level_to_kill} -> + let* head_level = + (Rpc_services.get_level + ~node_addr [@profiler.record_s {verbosity = Notice} "get_level"]) + in + if head_level >= level_to_kill then ( + let*! () = + Events.(emit stopping_agent) (Agent.name, baker.protocol_hash) + in + Lwt.wakeup + baker.process.canceller + 0 [@profiler.record_f {verbosity = Notice} "kill old baker"] ; + state.old_baker <- None ; + return_unit) + else return_unit + + (* ---- Baker and Chain Monitoring ---- *) + + (** [monitor_heads ~node_addr] creates a stream which returns the data of the heads of the current network; this information is received from the RPC calls at the endpoint given by [~node_addr]. *) -let monitor_heads ~node_addr = - let open Lwt_result_syntax in - let uri = Format.sprintf "%s/monitor/heads/main" node_addr in - let* _, body = Rpc_services.request_uri ~node_addr ~uri in - let cohttp_stream = Cohttp_lwt.Body.to_stream body in - let buffer = Buffer.create 2048 in - let stream, push = Lwt_stream.create () in - let on_chunk v = push (Some v) and on_close () = push None in - let rec loop () = - let*! v = Lwt_stream.get cohttp_stream in - match v with - | None -> - on_close () ; - Lwt.return_unit - | Some chunk -> - Buffer.add_string buffer chunk ; - let data = Buffer.contents buffer in - Buffer.reset buffer ; - on_chunk data ; - loop () - in - ignore (loop () : unit Lwt.t) ; - return stream - -(** [monitor_voting_periods ~state head_stream] continuously monitors [heads_stream] + let monitor_heads ~node_addr = + let open Lwt_result_syntax in + let uri = Format.sprintf "%s/monitor/heads/main" node_addr in + let* _, body = Rpc_services.request_uri ~node_addr ~uri in + let cohttp_stream = Cohttp_lwt.Body.to_stream body in + let buffer = Buffer.create 2048 in + let stream, push = Lwt_stream.create () in + let on_chunk v = push (Some v) and on_close () = push None in + let rec loop () = + let*! v = Lwt_stream.get cohttp_stream in + match v with + | None -> + on_close () ; + Lwt.return_unit + | Some chunk -> + Buffer.add_string buffer chunk ; + let data = Buffer.contents buffer in + Buffer.reset buffer ; + on_chunk data ; + loop () + in + ignore (loop () : unit Lwt.t) ; + return stream + + (** [monitor_voting_periods ~state head_stream] continuously monitors [heads_stream] to detect protocol changes. It will: - Shut down an old baker it its time has come; - Spawn and "hot-swap" to a new baker if the next protocol hash is different. The voting period information is used for logging purposes. *) -let monitor_voting_periods ~state head_stream = - let open Lwt_result_syntax in - let node_addr = state.node_endpoint in - let rec loop () = - let*! v = Lwt_stream.get head_stream in - match v with - | None -> tzfail Lost_node_connection - | Some _tick -> - let* block_hash = - (Rpc_services.get_block_hash - ~node_addr - [@profiler.record_s {verbosity = Notice} "get_block_hash"]) - in - () - [@profiler.reset_block_section {profiler_module = Profiler} block_hash] ; - let* period_kind, remaining = - (Rpc_services.get_current_period - ~node_addr - [@profiler.record_s {verbosity = Notice} "get_current_period"]) - in - let*! () = - Events.(emit period_status) (block_hash, period_kind, remaining) - in - let* () = - (maybe_kill_old_baker - state - node_addr - [@profiler.record_s {verbosity = Notice} "maybe_kill_old_baker"]) - in - let* next_protocol_hash = - (Rpc_services.get_next_protocol_hash - ~node_addr - [@profiler.record_s {verbosity = Notice} "get_next_protocol_hash"]) - in - let* current_protocol_hash = - match state.current_baker with - | None -> tzfail Missing_current_baker - | Some baker -> return baker.protocol_hash - in - let* () = - if not (Protocol_hash.equal current_protocol_hash next_protocol_hash) - then - let* head_level = - (Rpc_services.get_level - ~node_addr - [@profiler.record_s {verbosity = Notice} "get_level"]) - in - (hot_swap_baker - ~state - ~current_protocol_hash - ~next_protocol_hash - ~level_to_kill_old_baker: - (head_level + Parameters.extra_levels_for_old_baker) - [@profiler.record_s {verbosity = Notice} "hot_swap_baker"]) - else return_unit - in - loop () - in - loop () + let monitor_voting_periods ~state head_stream = + let open Lwt_result_syntax in + let node_addr = state.node_endpoint in + let rec loop () = + let*! v = Lwt_stream.get head_stream in + match v with + | None -> tzfail Lost_node_connection + | Some _tick -> + let* block_hash = + (Rpc_services.get_block_hash + ~node_addr + [@profiler.record_s {verbosity = Notice} "get_block_hash"]) + in + () + [@profiler.reset_block_section + {profiler_module = Profiler} block_hash] ; + let* period_kind, remaining = + (Rpc_services.get_current_period + ~node_addr + [@profiler.record_s {verbosity = Notice} "get_current_period"]) + in + let*! () = + Events.(emit period_status) (block_hash, period_kind, remaining) + in + let* () = + (maybe_kill_old_baker + state + node_addr + [@profiler.record_s {verbosity = Notice} "maybe_kill_old_baker"]) + in + let* next_protocol_hash = + (Rpc_services.get_next_protocol_hash + ~node_addr + [@profiler.record_s {verbosity = Notice} "get_next_protocol_hash"]) + in + let* current_protocol_hash = + match state.current_baker with + | None -> tzfail (Missing_current_agent Agent.name) + | Some baker -> return baker.protocol_hash + in + let* () = + if + not (Protocol_hash.equal current_protocol_hash next_protocol_hash) + then + let* head_level = + (Rpc_services.get_level + ~node_addr + [@profiler.record_s {verbosity = Notice} "get_level"]) + in + (hot_swap_baker + ~state + ~current_protocol_hash + ~next_protocol_hash + ~level_to_kill_old_baker: + (head_level + Parameters.extra_levels_for_old_baker) + [@profiler.record_s {verbosity = Notice} "hot_swap_baker"]) + else return_unit + in + loop () + in + loop () -(** [baker_thread ~state] monitors the current baker thread for any potential error, and + (** [baker_thread ~state] monitors the current baker thread for any potential error, and it propagates any error that can appear. *) -let baker_thread ~state = - let open Lwt_result_syntax in - let*! retcode = - match state.current_baker with - | Some baker -> baker.process.thread - | None -> Lwt.return 0 - in - if retcode = 0 then return_unit else tzfail Baker_process_error - -(* ---- Agnostic Baker Bootstrap ---- *) - -(** [may_start_initial_baker state] recursively waits for an [active] protocol + let baker_thread ~state = + let open Lwt_result_syntax in + let*! retcode = + match state.current_baker with + | Some baker -> baker.process.thread + | None -> Lwt.return 0 + in + if retcode = 0 then return_unit else tzfail (Agent_process_error Agent.name) + + (* ---- Agnostic Baker Bootstrap ---- *) + + (** [may_start_initial_baker state] recursively waits for an [active] protocol and spawns a baker for it. If the protocol is [frozen] (not [active] anymore), it waits for a head with an [active] protocol. *) -let may_start_initial_baker state = - let open Lwt_result_syntax in - let rec may_start ?last_known_proto ~head_stream () = - let* protocol_hash = - Rpc_services.get_next_protocol_hash ~node_addr:state.node_endpoint + let may_start_initial_baker state = + let open Lwt_result_syntax in + let rec may_start ?last_known_proto ~head_stream () = + let* protocol_hash = + Rpc_services.get_next_protocol_hash ~node_addr:state.node_endpoint + in + let proto_status = Parameters.protocol_status protocol_hash in + let*! () = + match last_known_proto with + | None -> Lwt.return_unit + | Some h -> + if not (Protocol_hash.equal h protocol_hash) then + Events.(emit protocol_encountered) (proto_status, protocol_hash) + else Lwt.return_unit + in + match proto_status with + | Active -> + let* current_baker = spawn_baker protocol_hash in + state.current_baker <- Some current_baker ; + return_unit + | Frozen -> ( + let* head_stream = + match head_stream with + | Some v -> return v + | None -> + let*! () = + Events.(emit protocol_encountered) + (proto_status, protocol_hash) + in + let*! () = Events.(emit waiting_for_active_protocol) () in + monitor_heads ~node_addr:state.node_endpoint + in + let*! v = Lwt_stream.get head_stream in + match v with + | Some _tick -> + may_start + ~last_known_proto:protocol_hash + ~head_stream:(Some head_stream) + () + | None -> tzfail Lost_node_connection) in - let proto_status = Parameters.protocol_status protocol_hash in - let*! () = - match last_known_proto with - | None -> Lwt.return_unit - | Some h -> - if not (Protocol_hash.equal h protocol_hash) then - Events.(emit protocol_encountered) (proto_status, protocol_hash) - else Lwt.return_unit + may_start ~head_stream:None () + + let create ~node_endpoint ~keep_alive = + {node_endpoint; current_baker = None; old_baker = None; keep_alive} + + let run state = + let open Lwt_result_syntax in + let node_addr = state.node_endpoint in + let*! () = Events.(emit starting_daemon) Agent.name in + let _ccid = + Lwt_exit.register_clean_up_callback ~loc:__LOC__ (fun _ -> + let*! () = Events.(emit stopping_daemon) Agent.name in + Lwt.return_unit) in - match proto_status with - | Active -> - let* current_baker = spawn_baker protocol_hash in - state.current_baker <- Some current_baker ; - return_unit - | Frozen -> ( - let* head_stream = - match head_stream with - | Some v -> return v - | None -> - let*! () = - Events.(emit protocol_encountered) (proto_status, protocol_hash) - in - let*! () = Events.(emit waiting_for_active_protocol) () in - monitor_heads ~node_addr:state.node_endpoint - in - let*! v = Lwt_stream.get head_stream in - match v with - | Some _tick -> - may_start - ~last_known_proto:protocol_hash - ~head_stream:(Some head_stream) - () - | None -> tzfail Lost_node_connection) - in - may_start ~head_stream:None () - -let create ~node_endpoint ~keep_alive = - {node_endpoint; current_baker = None; old_baker = None; keep_alive} - -let run state = - let open Lwt_result_syntax in - let node_addr = state.node_endpoint in - let*! () = Events.(emit starting_daemon) () in - let _ccid = - Lwt_exit.register_clean_up_callback ~loc:__LOC__ (fun _ -> - let*! () = Events.(emit stopping_daemon) () in - Lwt.return_unit) - in - let* () = - if state.keep_alive then - retry_on_disconnection - ~emit:(Events.emit Agnostic_baker_events.cannot_connect) - node_addr - (fun () -> may_start_initial_baker state) - else may_start_initial_baker state - in - let monitor_voting_periods () = - let* head_stream = monitor_heads ~node_addr in - monitor_voting_periods ~state head_stream - in - (* Monitoring voting periods through heads monitoring to avoid - missing UAUs. *) - Lwt.pick - [ - (* We do not care if --keep-alive is provided, if the baker thread doesn't - have the argument it'll abort the process anyway. *) - retry_on_disconnection - ~emit:(fun _ -> Lwt.return_unit) - node_addr - monitor_voting_periods; - baker_thread ~state; - ] + let* () = + if state.keep_alive then + retry_on_disconnection + ~emit:(Events.emit Events.cannot_connect) + node_addr + (fun () -> may_start_initial_baker state) + else may_start_initial_baker state + in + let monitor_voting_periods () = + let* head_stream = monitor_heads ~node_addr in + monitor_voting_periods ~state head_stream + in + (* Monitoring voting periods through heads monitoring to avoid + missing UAUs. *) + Lwt.pick + [ + (* We do not care if --keep-alive is provided, if the baker thread doesn't + have the argument it'll abort the process anyway. *) + retry_on_disconnection + ~emit:(fun _ -> Lwt.return_unit) + node_addr + monitor_voting_periods; + baker_thread ~state; + ] +end + +module Baker = Make_daemon (Baker_agent) +module Accuser = Make_daemon (Accuser_agent) diff --git a/src/lib_agnostic_baker/daemon.mli b/src/lib_agnostic_baker/daemon.mli index 987847b692bdbe897c1b78500ed32602d2484de5..0b6572ae313f76d0fddefe68e4c13d4a4524fc33 100644 --- a/src/lib_agnostic_baker/daemon.mli +++ b/src/lib_agnostic_baker/daemon.mli @@ -6,14 +6,17 @@ (* *) (*****************************************************************************) -(** Daemon handling the baker's life cycle. +(** Daemon handling the an agent's life cycle. + + The current possible agents are the accuser and the baker, and the corresponding + daemons are given by [Accuser] and [Baker], respectively. It is used to [create] and [run] a protocol-agnostic process which uses the existing - baking processes in an adaptive way, depending on the current protocol obtained + protocol processes in an adaptive way, depending on the current protocol obtained from the chain. It relies on a [state] which contains the [endpoint] to contact the running node, - together with the current baker which is being run. + together with the current agent which is being run. To do so, it also spawns a "monitoring" process which follows the heads of the chain, as reported by the node from the [state], more precisely which monitors @@ -21,11 +24,16 @@ process. *) -type t +module type AGNOSTIC_DAEMON = sig + type t + + (** [create ~node_endpoint ~keep_alive] returns a non initialized daemon. *) + val create : node_endpoint:string -> keep_alive:bool -> t + + (** [run daemon] Runs the daemon responsible for the spawn/stop of the daemons. *) + val run : t -> unit tzresult Lwt.t +end -(** [create ~node_endpoint ~keep_alive] returns a non initialized daemon. *) -val create : node_endpoint:string -> keep_alive:bool -> t +module Baker : AGNOSTIC_DAEMON -(** [run daemon] Runs the daemon responsible for the spawn/stop of the - baker daemons. *) -val run : t -> unit tzresult Lwt.t +module Accuser : AGNOSTIC_DAEMON diff --git a/src/lib_agnostic_baker/agnostic_baker_errors.ml b/src/lib_agnostic_baker/errors.ml similarity index 65% rename from src/lib_agnostic_baker/agnostic_baker_errors.ml rename to src/lib_agnostic_baker/errors.ml index f0545bc1875d2452035e8014efe5ec132e694011..e065c615d06f46cb7acec38c0057e26670b323df 100644 --- a/src/lib_agnostic_baker/agnostic_baker_errors.ml +++ b/src/lib_agnostic_baker/errors.ml @@ -10,13 +10,13 @@ type error += | Lost_node_connection | Cannot_connect_to_node of string | Cannot_decode_node_data of string - | Missing_current_baker - | Baker_process_error + | Missing_current_agent of string + | Agent_process_error of string let () = Error_monad.register_error_kind `Permanent - ~id:"agnostic_baker.lost_node_connection" + ~id:"agnostic_agent.lost_node_connection" ~title:"Lost node connection" ~description:"Connection with node lost." ~pp:(fun ppf () -> Format.fprintf ppf "Connection with node was lost") @@ -25,7 +25,7 @@ let () = (fun () -> Lost_node_connection) ; Error_monad.register_error_kind `Permanent - ~id:"agnostic_baker.cannot_connect_to_node" + ~id:"agnostic_agent.cannot_connect_to_node" ~title:"Cannot connect to node" ~description:"Cannot connect to node." ~pp:(fun ppf uri -> @@ -38,7 +38,7 @@ let () = (fun uri -> Cannot_connect_to_node uri) ; Error_monad.register_error_kind `Permanent - ~id:"agnostic_baker.cannot_decode_node_data" + ~id:"agnostic_agent.cannot_decode_node_data" ~title:"Cannot decode node data" ~description:"Cannot decode node data." ~pp:(fun ppf err -> Format.fprintf ppf "Cannot decode node data: %s" err) @@ -47,20 +47,20 @@ let () = (fun err -> Cannot_decode_node_data err) ; Error_monad.register_error_kind `Permanent - ~id:"agnostic_baker.missing_current_baker" - ~title:"Missing current baker" - ~description:"The current baker process is missing." - ~pp:(fun ppf () -> Format.fprintf ppf "Missing current baker") - Data_encoding.(unit) - (function Missing_current_baker -> Some () | _ -> None) - (fun () -> Missing_current_baker) ; + ~id:"agnostic_agent.missing_current_agent" + ~title:"Missing current agent" + ~description:"The current agent process is missing." + ~pp:(fun ppf agent -> Format.fprintf ppf "Missing current %s" agent) + Data_encoding.(obj1 (req "agent" string)) + (function Missing_current_agent agent -> Some agent | _ -> None) + (fun agent -> Missing_current_agent agent) ; Error_monad.register_error_kind `Permanent - ~id:"agnostic_baker.baker_process_error" - ~title:"Underlying baker process error" - ~description:"There is an error in the underlying baker process." - ~pp:(fun ppf () -> - Format.fprintf ppf "Error in the underlying baker process") - Data_encoding.(unit) - (function Baker_process_error -> Some () | _ -> None) - (fun () -> Baker_process_error) + ~id:"agnostic_agent.agent_process_error" + ~title:"Underlying agent process error" + ~description:"There is an error in the underlying agent process." + ~pp:(fun ppf agent -> + Format.fprintf ppf "Error in the underlying %s process" agent) + Data_encoding.(obj1 (req "agent" string)) + (function Agent_process_error agent -> Some agent | _ -> None) + (fun agent -> Agent_process_error agent) diff --git a/src/lib_agnostic_baker/agnostic_baker_events.ml b/src/lib_agnostic_baker/events.ml similarity index 71% rename from src/lib_agnostic_baker/agnostic_baker_events.ml rename to src/lib_agnostic_baker/events.ml index a24c0f396b5109efc138a13a513def716903639e..2830f2b3524e12ce87f4a77ff166a03f8f1744aa 100644 --- a/src/lib_agnostic_baker/agnostic_baker_events.ml +++ b/src/lib_agnostic_baker/events.ml @@ -7,56 +7,59 @@ include Internal_event.Simple -let section = ["agnostic-baker"] +let section = ["agnostic-agent"] let alternative_color = Internal_event.Green (* Notice *) -let starting_baker = - declare_1 +let starting_agent = + declare_2 ~section ~alternative_color ~level:Notice - ~name:"starting_baker" - ~msg:"starting baker for protocol {proto}" + ~name:"starting_agent" + ~msg:"starting {agent} for protocol {proto}" + ("agent", string) ("proto", Protocol_hash.encoding) - ~pp1:Protocol_hash.pp_short + ~pp2:Protocol_hash.pp_short -let baker_running = - declare_1 +let agent_running = + declare_2 ~section ~alternative_color ~level:Notice - ~name:"baker_running" - ~msg:"baker for protocol {proto} is now running" + ~name:"agent_running" + ~msg:"{agent} for protocol {proto} is now running" + ("agent", string) ("proto", Protocol_hash.encoding) - ~pp1:Protocol_hash.pp_short + ~pp2:Protocol_hash.pp_short -let stopping_baker = - declare_1 +let stopping_agent = + declare_2 ~section ~level:Notice - ~name:"stopping_baker" - ~msg:"stopping baker for protocol {proto}" + ~name:"stopping_agent" + ~msg:"stopping {agent} for protocol {proto}" + ("agent", string) ("proto", Protocol_hash.encoding) - ~pp1:Protocol_hash.pp_short + ~pp2:Protocol_hash.pp_short let starting_daemon = - declare_0 + declare_1 ~section ~alternative_color ~level:Notice ~name:"starting_daemon" - ~msg:"agnostic baker started" - () + ~msg:"agnostic {agent} started" + ("agent", string) let stopping_daemon = - declare_0 + declare_1 ~section ~level:Notice ~name:"stopping_daemon" - ~msg:"stopping agnostic daemon" - () + ~msg:"stopping agnostic {agent} daemon" + ("agent", string) let protocol_encountered = declare_2 @@ -69,16 +72,17 @@ let protocol_encountered = ("proto_hash", Protocol_hash.encoding) ~pp2:Protocol_hash.pp_short -let become_old_baker = - declare_2 +let become_old_agent = + declare_3 ~section ~level:Notice - ~name:"become_old_baker" + ~name:"become_old_agent" ~msg: - "The old baker for protocol {proto_hash} will be shut down at level \ + "The old {agent} for protocol {proto_hash} will be shut down at level \ {level_to_kill}." + ("agent", string) ("proto_hash", Protocol_hash.encoding) - ~pp1:Protocol_hash.pp_short + ~pp2:Protocol_hash.pp_short ("level_to_kill", int31) let waiting_for_active_protocol = @@ -109,7 +113,7 @@ let cannot_connect = ~section ~alternative_color ~level:Error - ~name:"agnostic_baker_cannot_connect" + ~name:"cannot_connect" ~msg:"Cannot connect to node. {message}" ~pp1:Format.pp_print_string ("message", Data_encoding.string) diff --git a/src/lib_agnostic_baker/rpc_services.ml b/src/lib_agnostic_baker/rpc_services.ml index e959b25d910613c4e2c9ba9429f40a35100f288c..b246f07ff106e8f2a7d4cd9eca61e401c1fe982d 100644 --- a/src/lib_agnostic_baker/rpc_services.ml +++ b/src/lib_agnostic_baker/rpc_services.ml @@ -7,7 +7,7 @@ (*****************************************************************************) open Cohttp_lwt_unix -open Agnostic_baker_errors +open Errors (* RPC helper functions *) diff --git a/tezt/lib_tezos/constant.ml b/tezt/lib_tezos/constant.ml index d63749035c72d3723354e48c8b90a78538ba9cc2..6c4ada6ec74d357746b5ad87c5a00f1b66f22448 100644 --- a/tezt/lib_tezos/constant.ml +++ b/tezt/lib_tezos/constant.ml @@ -100,6 +100,8 @@ let octez_baker_rio = let octez_baker_alpha = Uses.make ~tag:"baker_alpha" ~path:"./octez-baker-alpha" () +let octez_accuser = Uses.make ~tag:"accuser" ~path:"./octez-accuser" () + let yes_wallet = Uses.make ~tag:"yes_wallet" diff --git a/tezt/lib_wrapper/expected/tezt_wrapper.ml/runtime-dependency-tags.out b/tezt/lib_wrapper/expected/tezt_wrapper.ml/runtime-dependency-tags.out index c9fe5629afc997aba9021160a0e109ce2cc14667..93ca0d5358c472903d94b1a1efcfbc91dbbde769 100644 --- a/tezt/lib_wrapper/expected/tezt_wrapper.ml/runtime-dependency-tags.out +++ b/tezt/lib_wrapper/expected/tezt_wrapper.ml/runtime-dependency-tags.out @@ -7,6 +7,7 @@ failed_migration: etherlink/kernel_latest/kernel/tests/resources/failed_migratio ghostnet_kernel: etherlink/kernel_latest/kernel/tests/resources/ghostnet_kernel.wasm mainnet_kernel: etherlink/kernel_latest/kernel/tests/resources/mainnet_kernel.wasm evm_kernel: evm_kernel.wasm +accuser: octez-accuser accuser_psquebec: octez-accuser-PsQuebec accuser_psriotum: octez-accuser-PsRiotum accuser_alpha: octez-accuser-alpha diff --git a/tezt/tests/agnostic_baker_test.ml b/tezt/tests/agnostic_baker_test.ml index 8edfae35904ea578464dba6ba441306cea297522..c38e574cf20b428d7964a2baad3f2b8fcc3541fa 100644 --- a/tezt/tests/agnostic_baker_test.ml +++ b/tezt/tests/agnostic_baker_test.ml @@ -30,11 +30,11 @@ let wait_for_active_protocol_waiting agnostic_baker = (fun _json -> Some ()) let wait_for_become_old_baker agnostic_baker = - Agnostic_baker.wait_for agnostic_baker "become_old_baker.v0" (fun _json -> + Agnostic_baker.wait_for agnostic_baker "become_old_agent.v0" (fun _json -> Some ()) let wait_for_stopping_baker agnostic_baker = - Agnostic_baker.wait_for agnostic_baker "stopping_baker.v0" (fun _json -> + Agnostic_baker.wait_for agnostic_baker "stopping_agent.v0" (fun _json -> Some ()) let remote_sign client = @@ -221,10 +221,7 @@ let test_keep_alive = let* () = Process.check_error ~msg:(rex "Cannot connect to node") process in (* Start the baker with no node running and [--keep-alive], it'll wait. *) let wait_for_cannot_connect = - Agnostic_baker.wait_for - baker - "agnostic_baker_cannot_connect.v0" - (fun _json -> Some ()) + Agnostic_baker.wait_for baker "cannot_connect.v0" (fun _json -> Some ()) in let* () = Agnostic_baker.run ~extra_arguments:["--keep-alive"] baker and* () = wait_for_cannot_connect in diff --git a/tobi/config b/tobi/config index 7d062929c2f0b5277c7d683ba77efa1e9ee7d116..a5eeee27d2c730d618480e596aadd882911b1fae 100644 --- a/tobi/config +++ b/tobi/config @@ -47,6 +47,7 @@ internal-devtools: devtools/tztop internal-devtools_proto-context-du: devtools/proto_context_du kaitai: client-libs/kaitai-ocaml/src, client-libs/kaitai-ocaml/test kaitai-of-data-encoding: client-libs/lib_kaitai_of_data_encoding, client-libs/lib_kaitai_of_data_encoding/test +octez-accuser: src/bin_agnostic_accuser octez-accuser-PsQuebec: src/proto_021_PsQuebec/bin_accuser octez-accuser-PsRiotum: src/proto_022_PsRiotum/bin_accuser octez-accuser-alpha: src/proto_alpha/bin_accuser