diff --git a/.gitignore b/.gitignore index 453fa43808b5bc3ec5226adaf53621c82a9e8945..69e825ef3dcc940cb0aa222dd2e4ecc8ce812651 100644 --- a/.gitignore +++ b/.gitignore @@ -48,6 +48,7 @@ __pycache__ /octez-tps-evaluation-* /tezos-smart-rollup-node-* /octez-smart-rollup-node-* +/octez-smart-rollup-sequencer-node /tezos-smart-rollup-client-* /octez-smart-rollup-client-* /octez-smart-rollup-wasm-* diff --git a/.gitlab/ci/jobs/packaging/opam_package.yml b/.gitlab/ci/jobs/packaging/opam_package.yml index 0064c39e5eaccce090df488afd4171948780905a..2bbcc2c291b4da795eef8ad667ed814a84d11c55 100644 --- a/.gitlab/ci/jobs/packaging/opam_package.yml +++ b/.gitlab/ci/jobs/packaging/opam_package.yml @@ -430,6 +430,8 @@ opam:octez-smart-rollup-node-PtNairob: # Ignoring unreleased package octez-smart-rollup-sequencer. +# Ignoring unreleased package octez-smart-rollup-sequencer-node. + # Ignoring unreleased package octez-smart-rollup-wasm-benchmark. opam:octez-smart-rollup-wasm-benchmark-lib: diff --git a/.gitlab/ci/jobs/packaging/opam_package_executables.yml b/.gitlab/ci/jobs/packaging/opam_package_executables.yml index 4f7cee6553b33607925e59ae7fca2b87e28ee483..ef426c47f967a588f6e3cf5b49184ee63b4f8720 100644 --- a/.gitlab/ci/jobs/packaging/opam_package_executables.yml +++ b/.gitlab/ci/jobs/packaging/opam_package_executables.yml @@ -320,6 +320,8 @@ opam:octez-smart-rollup-node-PtNairob: # Ignoring unreleased package octez-smart-rollup-node-alpha. +# Ignoring unreleased package octez-smart-rollup-sequencer-node. + opam:octez-smart-rollup-wasm-debugger: extends: - .opam_template diff --git a/dune-project b/dune-project index 5cde156fde6fe13eb81dfc0c38736840d1ea02d7..46fc0ff80d7b13c74d90a47935fd9a6985a86b33 100644 --- a/dune-project +++ b/dune-project @@ -45,6 +45,7 @@ (package (name octez-smart-rollup-node-PtNairob)) (package (name octez-smart-rollup-node-alpha)) (package (name octez-smart-rollup-sequencer)(allow_empty)) +(package (name octez-smart-rollup-sequencer-node)) (package (name octez-smart-rollup-wasm-benchmark)(allow_empty)) (package (name octez-smart-rollup-wasm-benchmark-lib)(allow_empty)) (package (name octez-smart-rollup-wasm-debugger)) diff --git a/manifest/main.ml b/manifest/main.ml index dd91c455ca13cd3f80e7be655b498094edbaa6e1..1f43d3a32bc8a51f6be228e8e6621540aec0ce27 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -4308,6 +4308,8 @@ module Protocol : sig val octez_sc_rollup_layer2 : t -> target option + val octez_sc_rollup_node : t -> target option + val baking_exn : t -> target val genesis : t @@ -4424,12 +4426,13 @@ end = struct benchmarks_proto : target option; baking : target option; octez_sc_rollup_layer2 : target option; + octez_sc_rollup_node : target option; } let make ?client ?client_commands ?client_commands_registration ?baking_commands_registration ?plugin ?plugin_registerer ?dal ?dac ?test_helpers ?parameters ?benchmarks_proto ?octez_sc_rollup_layer2 - ?baking ~status ~name ~main ~embedded () = + ?octez_sc_rollup_node ?baking ~status ~name ~main ~embedded () = { status; name; @@ -4448,6 +4451,7 @@ end = struct benchmarks_proto; baking; octez_sc_rollup_layer2; + octez_sc_rollup_node; } let all_rev : t list ref = ref [] @@ -4508,6 +4512,8 @@ end = struct let octez_sc_rollup_layer2 p = p.octez_sc_rollup_layer2 + let octez_sc_rollup_node p = p.octez_sc_rollup_node + (* N as in "protocol number in the Alpha family". *) module N = struct (* This function is asymmetrical on purpose: we don't want to compare @@ -6426,6 +6432,7 @@ let hash = Protocol.hash ?benchmarks_proto ?baking ?octez_sc_rollup_layer2 + ?octez_sc_rollup_node () let active = register_alpha_family Active @@ -7393,7 +7400,7 @@ let evm_proxy_lib = rope; ] -let _octez_scoru_sequencer = +let octez_scoru_sequencer = private_lib "octez_smart_rollup_sequencer" ~path:"src/lib_scoru_sequencer" @@ -7405,11 +7412,34 @@ let _octez_scoru_sequencer = |> open_ ~m:"TzPervasives.Error_monad.Legacy_monad_globals"; Protocol.(octez_sc_rollup_layer2 alpha |> if_some |> open_); Protocol.(main alpha) |> open_; + Protocol.(octez_sc_rollup_node alpha) |> if_some; octez_rpc; octez_rpc_http; octez_rpc_http_server; ] +let _sc_sequencer_node = + public_exe + "octez-smart-rollup-sequencer-node" + ~internal_name:"main_sequencer_node" + ~path:"src/bin_sequencer_node" + ~synopsis:"Smart rollup sequencer node (low-latency node)" + ~release_status:Experimental + ~with_macos_security_framework:true + ~deps: + [ + octez_base |> open_ |> open_ ~m:"TzPervasives" + |> open_ ~m:"TzPervasives.Error_monad.Legacy_monad_globals"; + octez_clic; + octez_client_base |> open_; + octez_client_base_unix |> open_; + octez_client_commands |> open_; + octez_smart_rollup_node_lib |> open_; + Protocol.(client alpha) |> if_some |> open_; + Protocol.(octez_sc_rollup_node alpha) |> if_some |> open_; + octez_scoru_sequencer |> open_; + ] + let _evm_proxy = public_exe (sf "octez-evm-proxy-server") diff --git a/opam/octez-smart-rollup-sequencer-node.opam b/opam/octez-smart-rollup-sequencer-node.opam new file mode 100644 index 0000000000000000000000000000000000000000..eb37c844e4c8b5276fde18a3f61d721d1084e172 --- /dev/null +++ b/opam/octez-smart-rollup-sequencer-node.opam @@ -0,0 +1,28 @@ +# 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.0" } + "ocaml" { >= "4.14" } + "tezos-base" + "tezos-clic" + "tezos-client-base" + "tezos-client-base-unix" + "tezos-client-commands" + "octez-smart-rollup-node" + "tezos-client-alpha" + "octez-smart-rollup-node-alpha" + "octez-smart-rollup-sequencer" +] +build: [ + ["rm" "-r" "vendors" "contrib"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Smart rollup sequencer node (low-latency node)" diff --git a/opam/octez-smart-rollup-sequencer.opam b/opam/octez-smart-rollup-sequencer.opam index e8c3b10c566cb17d1d75081fbd694dac00cb5952..df4f31b4c742faefddeebdeb22d09e31a8a73f19 100644 --- a/opam/octez-smart-rollup-sequencer.opam +++ b/opam/octez-smart-rollup-sequencer.opam @@ -13,6 +13,7 @@ depends: [ "tezos-base" "tezos-smart-rollup-layer2-alpha" "tezos-protocol-alpha" + "octez-smart-rollup-node-alpha" "tezos-rpc" "tezos-rpc-http" "tezos-rpc-http-server" diff --git a/script-inputs/experimental-executables b/script-inputs/experimental-executables index 618740486052d21fd5d02367205728d2c6e2e288..c6c23602a2cb465c38a490a06c8089976020f211 100644 --- a/script-inputs/experimental-executables +++ b/script-inputs/experimental-executables @@ -1,4 +1,5 @@ octez-evm-proxy-server +octez-smart-rollup-sequencer-node octez-dac-client octez-dac-node octez-dal-node diff --git a/src/bin_sequencer_node/dune b/src/bin_sequencer_node/dune new file mode 100644 index 0000000000000000000000000000000000000000..270c52c4dee1068f592b81572ad4d6a0625c6991 --- /dev/null +++ b/src/bin_sequencer_node/dune @@ -0,0 +1,34 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(executable + (name main_sequencer_node) + (public_name octez-smart-rollup-sequencer-node) + (package octez-smart-rollup-sequencer-node) + (instrumentation (backend bisect_ppx)) + (libraries + tezos-base + tezos-clic + tezos-client-base + tezos-client-base-unix + tezos-client-commands + octez-smart-rollup-node + tezos-client-alpha + octez_smart_rollup_node_alpha + octez_smart_rollup_sequencer) + (link_flags + (:standard) + (:include %{workspace_root}/static-link-flags.sexp) + (:include %{workspace_root}/macos-link-flags.sexp)) + (flags + (:standard) + -open Tezos_base + -open Tezos_base.TzPervasives + -open Tezos_base.TzPervasives.Error_monad.Legacy_monad_globals + -open Tezos_client_base + -open Tezos_client_base_unix + -open Tezos_client_commands + -open Octez_smart_rollup_node + -open Tezos_client_alpha + -open Octez_smart_rollup_node_alpha + -open Octez_smart_rollup_sequencer)) diff --git a/src/bin_sequencer_node/main_sequencer_node.ml b/src/bin_sequencer_node/main_sequencer_node.ml new file mode 100644 index 0000000000000000000000000000000000000000..a054fe89dd49d34678526be0de6f0ea169012966 --- /dev/null +++ b/src/bin_sequencer_node/main_sequencer_node.ml @@ -0,0 +1,228 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2021 Nomadic Labs, *) +(* Copyright (c) 2022 Trili Tech, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +module Sc_sequencer = Octez_smart_rollup_sequencer +module Sc_rollup_node = Octez_smart_rollup_node_alpha + +let group = + { + Tezos_clic.name = "sc_sequencer.node"; + title = "Commands related to the smart rollup sequencer node."; + } + +include Cli.Binary_dependent_args (struct + let binary_name = "sequencer node" +end) + +let sc_operator_pkh next = + let open Lwt_result_syntax in + Tezos_clic.param + ~name:"operator" + ~desc:"Public key hash, or alias, of a sequencer node operator." + ( Tezos_clic.parameter @@ fun cctxt s -> + let parse_pkh s = + let from_alias s = Client_keys.Public_key_hash.find cctxt s in + let from_key s = + match Signature.Public_key_hash.of_b58check_opt s with + | None -> + failwith "Could not read public key hash for sequencer operator" + | Some pkh -> return pkh + in + Client_aliases.parse_alternatives + [("alias", from_alias); ("key", from_key)] + s + in + match String.split ~limit:1 ':' s with + | [_] -> + let+ pkh = parse_pkh s in + `Default pkh + | [_purpose; _operator_s] -> + failwith "Purposes are not supported for a sequencer operator" + | _ -> + (* cannot happen due to String.split's implementation. *) + assert false ) + next + +let config_init_command = + let open Lwt_result_syntax in + let open Tezos_clic in + let open Cli in + command + ~group + ~desc:"Configure the sequencer node." + (args13 + force_switch + data_dir_arg + rpc_addr_arg + rpc_port_arg + metrics_addr_arg + reconnection_delay_arg + dac_observer_endpoint_arg + dac_timeout_arg + injector_retention_period_arg + injector_attempts_arg + injection_ttl_arg + log_kernel_debug_arg + boot_sector_file_arg) + (prefix "init" + @@ prefixes ["config"; "for"] + @@ sc_rollup_address_param + @@ prefixes ["with"; "operator"] + @@ sc_operator_pkh stop) + (fun ( force, + data_dir, + rpc_addr, + rpc_port, + metrics_addr, + reconnection_delay, + dac_observer_endpoint, + dac_timeout, + injector_retention_period, + injector_attempts, + injection_ttl, + log_kernel_debug, + boot_sector_file ) + sc_rollup_address + sc_sequencer_operator + cctxt -> + let*? config = + Configuration.Cli.configuration_from_args + ~rpc_addr + ~rpc_port + ~metrics_addr + ~loser_mode:None + ~reconnection_delay + ~dal_node_endpoint:None + ~dac_observer_endpoint + ~dac_timeout + ~injector_retention_period + ~injector_attempts + ~injection_ttl + ~mode:Configuration.Batcher + ~sc_rollup_address + ~boot_sector_file + ~sc_rollup_node_operators:[sc_sequencer_operator] + ~log_kernel_debug + in + let* () = Configuration.save ~force ~data_dir config in + let*! () = + cctxt#message + "Smart rollup node configuration written in %s" + (Configuration.config_filename ~data_dir) + in + return_unit) + +let run_command = + let open Tezos_clic in + let open Lwt_result_syntax in + let open Cli in + command + ~group + ~desc: + "Run the sequencer node daemon. Arguments overwrite values provided in \ + the configuration file." + (args13 + data_dir_arg + rpc_addr_arg + rpc_port_arg + metrics_addr_arg + reconnection_delay_arg + dac_observer_endpoint_arg + dac_timeout_arg + injector_retention_period_arg + injector_attempts_arg + injection_ttl_arg + log_kernel_debug_arg + log_kernel_debug_file_arg + boot_sector_file_arg) + (prefixes ["run"] @@ prefixes ["for"] @@ sc_rollup_address_param + @@ prefixes ["with"; "operator"] + @@ sc_operator_pkh stop) + (fun ( data_dir, + rpc_addr, + rpc_port, + metrics_addr, + reconnection_delay, + dac_observer_endpoint, + dac_timeout, + injector_retention_period, + injector_attempts, + injection_ttl, + log_kernel_debug, + log_kernel_debug_file, + boot_sector_file ) + sc_rollup_address + sc_sequencer_operator + cctxt -> + let* configuration = + Configuration.Cli.create_or_read_config + ~data_dir + ~rpc_addr + ~rpc_port + ~metrics_addr + ~loser_mode:None + ~reconnection_delay + ~dal_node_endpoint:None + ~dac_observer_endpoint + ~dac_timeout + ~injector_retention_period + ~injector_attempts + ~injection_ttl + ~mode:(Some Configuration.Batcher) + ~sc_rollup_address:(Some sc_rollup_address) + ~sc_rollup_node_operators:[sc_sequencer_operator] + ~log_kernel_debug + ~boot_sector_file + in + Sc_rollup_node.Daemon.run + ~data_dir + ?log_kernel_debug_file + configuration + ~daemon_components:(module Sc_sequencer.Components.Daemon_components) + (new Protocol_client_context.wrap_full cctxt)) + +(** Command to dump the rollup node metrics. *) +let dump_metrics = + let open Tezos_clic in + let open Lwt_result_syntax in + command + ~group + ~desc:"dump the sequencer available metrics in CSV format." + no_options + (prefixes ["dump-metrics"] @@ stop) + (fun () (cctxt : Client_context.full) -> + let*! metrics = + Prometheus.CollectorRegistry.collect Metrics.sc_rollup_node_registry + in + let*! () = cctxt#message "%a@." Metrics.print_csv_metrics metrics in + return_unit) + +let commands () = [config_init_command; run_command; dump_metrics] + +let select_commands _ctxt _ = + Lwt_result_syntax.return (commands () @ Client_helpers_commands.commands ()) + +let () = Client_main_run.run (module Daemon_config) ~select_commands diff --git a/src/lib_scoru_sequencer/configuration.ml b/src/lib_scoru_sequencer/components.ml similarity index 91% rename from src/lib_scoru_sequencer/configuration.ml rename to src/lib_scoru_sequencer/components.ml index cc358b05a3323698e2ec550492cf96aeee5b626f..262fb6eb637ff49a653f02434e22d8296d13a594 100644 --- a/src/lib_scoru_sequencer/configuration.ml +++ b/src/lib_scoru_sequencer/components.ml @@ -24,4 +24,9 @@ (* *) (*****************************************************************************) -type t = {rpc_addr : string; rpc_port : int} +module Sc_rollup_node = Octez_smart_rollup_node_alpha + +module Daemon_components = struct + module Batcher = Sc_rollup_node.Batcher + module RPC_server = Sc_rollup_node.RPC_server +end diff --git a/src/lib_scoru_sequencer/dune b/src/lib_scoru_sequencer/dune index 81ad590e144fcc60b8b061345418af54bd10a686..e6f40c06adf28d3092ff0c73a843812097389749 100644 --- a/src/lib_scoru_sequencer/dune +++ b/src/lib_scoru_sequencer/dune @@ -9,6 +9,7 @@ tezos-base tezos-smart-rollup-layer2-alpha tezos-protocol-alpha + octez_smart_rollup_node_alpha tezos-rpc tezos-rpc-http tezos-rpc-http-server) diff --git a/src/lib_scoru_sequencer/rpc_server.ml b/src/lib_scoru_sequencer/rpc_server.ml index 24b250b174a70aa3b4fb34230acd1ec2523bc80b..94ad50b7077ac268d93eb9487b051365b7a3449b 100644 --- a/src/lib_scoru_sequencer/rpc_server.ml +++ b/src/lib_scoru_sequencer/rpc_server.ml @@ -26,6 +26,7 @@ open Tezos_rpc_http_server open RPC_directory_helpers +open Octez_smart_rollup_node module Local_directory = Make_directory (struct include Sc_rollup_services.Local diff --git a/src/lib_scoru_sequencer/rpc_server.mli b/src/lib_scoru_sequencer/rpc_server.mli index baa5f328d9c0e62fc3124b2f4f3cfe51d1de18ec..209af654624d62e829733eb93e1b8435a59177f6 100644 --- a/src/lib_scoru_sequencer/rpc_server.mli +++ b/src/lib_scoru_sequencer/rpc_server.mli @@ -24,6 +24,7 @@ (*****************************************************************************) open Tezos_rpc_http_server +open Octez_smart_rollup_node (** [start node_ctxt config] starts an RPC server listening for requests on the port [config.rpc_port] and address [config.rpc_addr]. *) diff --git a/src/lib_smart_rollup_node/cli.ml b/src/lib_smart_rollup_node/cli.ml index 6f55fc2bd74e32ebd3cf4762b861d1e6f800fa85..9d81f8408d04a72afc949f99aa1a02846547248f 100644 --- a/src/lib_smart_rollup_node/cli.ml +++ b/src/lib_smart_rollup_node/cli.ml @@ -42,6 +42,8 @@ let sc_rollup_address_arg : (_, Client_context.full) Tezos_clic.arg = ~doc:"The smart rollup address (required when no configuration file exists)" (Smart_rollup_alias.Address.parameter ()) +(* Rollup node only arguments *) + let sc_rollup_node_operator_param next = let open Lwt_result_syntax in Tezos_clic.param @@ -114,34 +116,6 @@ let mode_arg = ~doc:(mode_doc ^ "\n(required when no configuration file exists)") mode_parameter -let string_parameter = - Tezos_clic.parameter (fun (_cctxt : Client_context.full) x -> - Lwt_result.return x) - -let int_parameter = - Tezos_clic.parameter (fun (cctxt : Client_context.full) p -> - try Lwt_result.return (int_of_string p) - with _ -> cctxt#error "Cannot read int") - -let rpc_addr_arg = - let default = Configuration.default_rpc_addr in - Tezos_clic.arg - ~long:"rpc-addr" - ~placeholder:"rpc-address|ip" - ~doc: - (Format.sprintf - "The address the smart rollup node listens to. Default value is %s" - default) - string_parameter - -let metrics_addr_arg = - Tezos_clic.arg - ~long:"metrics-addr" - ~placeholder: - "ADDR:PORT or :PORT (by default ADDR is localhost and PORT is 9933)" - ~doc:"The address of the smart rollup node metrics server." - string_parameter - let dal_node_endpoint_arg = Tezos_clic.arg ~long:"dal-node" @@ -155,16 +129,25 @@ let dal_node_endpoint_arg = (Tezos_clic.parameter (fun (_cctxt : Client_context.full) s -> Lwt.return_ok (Uri.of_string s))) -let dac_observer_endpoint_arg = +let loser_mode_arg = Tezos_clic.arg - ~long:"dac-observer" - ~placeholder:"dac-observer-endpoint" - ~doc: - (Format.sprintf - "The address of the DAC observer node from which the smart rollup \ - node downloads preimages requested through the reveal channel.") + ~long:"loser-mode" + ~placeholder:"mode" + ~doc:"Set the rollup node failure points (for test only!)." (Tezos_clic.parameter (fun (_cctxt : Client_context.full) s -> - Lwt.return_ok (Uri.of_string s))) + match Loser_mode.make s with + | Some t -> Lwt_result.return t + | None -> failwith "Invalid syntax for failure points")) + +(* Primitive argument parsers *) +let string_parameter = + Tezos_clic.parameter (fun (_cctxt : Client_context.full) x -> + Lwt_result.return x) + +let int_parameter = + Tezos_clic.parameter (fun (cctxt : Client_context.full) p -> + try Lwt_result.return (int_of_string p) + with _ -> cctxt#error "Cannot read int") let z_parameter = Tezos_clic.parameter (fun (cctxt : Client_context.full) s -> @@ -174,6 +157,87 @@ let z_parameter = return v with _ -> cctxt#error "Invalid number, must be a non negative number.") +module Binary_dependent_args (P : sig + val binary_name : string +end) = +struct + open P + + let rpc_addr_arg = + let default = Configuration.default_rpc_addr in + Tezos_clic.arg + ~long:"rpc-addr" + ~placeholder:"rpc-address|ip" + ~doc: + (Format.sprintf + "The address the %s listens to. Default value is %s" + binary_name + default) + string_parameter + + let metrics_addr_arg = + Tezos_clic.arg + ~long:"metrics-addr" + ~placeholder: + "ADDR:PORT or :PORT (by default ADDR is localhost and PORT is 9933)" + ~doc:(Format.sprintf "The address of the %s metrics server." binary_name) + string_parameter + + let dac_observer_endpoint_arg = + Tezos_clic.arg + ~long:"dac-observer" + ~placeholder:"dac-observer-endpoint" + ~doc: + (Format.sprintf + "The address of the DAC observer node from which the %s downloads \ + preimages requested through the reveal channel." + P.binary_name) + (Tezos_clic.parameter (fun (_cctxt : Client_context.full) s -> + Lwt.return_ok (Uri.of_string s))) + + let rpc_port_arg = + let default = Configuration.default_rpc_port |> string_of_int in + Tezos_clic.arg + ~long:"rpc-port" + ~placeholder:"rpc-port" + ~doc: + (Format.sprintf + "The port the %s listens to. Default value is %s" + binary_name + default) + int_parameter + + let data_dir_arg = + let default = Configuration.default_data_dir in + Tezos_clic.default_arg + ~long:"data-dir" + ~placeholder:"data-dir" + ~doc: + (Format.sprintf + "The path to the %s data directory. Default value is %s" + binary_name + default) + ~default + string_parameter + + let boot_sector_file_arg = + Tezos_clic.arg + ~long:"boot-sector-file" + ~placeholder:"file" + ~doc: + (Format.sprintf + "Path to the boot sector. The argument is optional, if the rollup \ + was originated via the smart rollup originate operation, the %s \ + will fetch the boot sector itself. This argument is required only \ + if it's a bootstrapped smart rollup." + binary_name) + (Tezos_clic.parameter (fun (_cctxt : Client_context.full) path -> + let open Lwt_result_syntax in + let*! exists = Lwt_unix.file_exists path in + if exists then return path + else failwith "Boot sector not found at path %S" path)) +end + let dac_timeout_arg = Tezos_clic.arg ~long:"dac-timeout" @@ -183,39 +247,6 @@ let dac_timeout_arg = preimage" z_parameter -let rpc_port_arg = - let default = Configuration.default_rpc_port |> string_of_int in - Tezos_clic.arg - ~long:"rpc-port" - ~placeholder:"rpc-port" - ~doc: - (Format.sprintf - "The port the smart rollup node listens to. Default value is %s" - default) - int_parameter - -let data_dir_arg = - let default = Configuration.default_data_dir in - Tezos_clic.default_arg - ~long:"data-dir" - ~placeholder:"data-dir" - ~doc: - (Format.sprintf - "The path to the smart rollup node data directory. Default value is %s" - default) - ~default - string_parameter - -let loser_mode_arg = - Tezos_clic.arg - ~long:"loser-mode" - ~placeholder:"mode" - ~doc:"Set the rollup node failure points (for test only!)." - (Tezos_clic.parameter (fun (_cctxt : Client_context.full) s -> - match Loser_mode.make s with - | Some t -> Lwt_result.return t - | None -> failwith "Invalid syntax for failure points")) - let reconnection_delay_arg = let default = Format.sprintf "%.1f" Configuration.default_reconnection_delay @@ -296,18 +327,3 @@ let log_kernel_debug_file_arg = ~placeholder:"file" ~doc:"" string_parameter - -let boot_sector_file_arg = - Tezos_clic.arg - ~long:"boot-sector-file" - ~placeholder:"file" - ~doc: - "Path to the boot sector. The argument is optional, if the rollup node \ - was originated via the smart rollup originate operation, the rollup \ - node will fetch the boot sector itself. This argument is required only \ - if it's a bootstrapped smart rollup." - (Tezos_clic.parameter (fun (_cctxt : Client_context.full) path -> - let open Lwt_result_syntax in - let*! exists = Lwt_unix.file_exists path in - if exists then return path - else failwith "Boot sector not found at path %S" path)) diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/main_sc_rollup_node_016_PtMumbai.ml b/src/proto_016_PtMumbai/bin_sc_rollup_node/main_sc_rollup_node_016_PtMumbai.ml index 43cf6f4451fb73ef31851de8122ca654fbfe3c9d..1f0e328c8b07d10966c9bab474aa072c7c468c2d 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/main_sc_rollup_node_016_PtMumbai.ml +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/main_sc_rollup_node_016_PtMumbai.ml @@ -24,6 +24,10 @@ (* *) (*****************************************************************************) +include Cli.Binary_dependent_args (struct + let binary_name = "smart rollup node" +end) + let group = { Tezos_clic.name = "sc_rollup.node"; diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_server.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_server.mli index 7830dad2505f33a4f67b31086d368c8c26e75514..6ce3fd2f3ec98de44ba3d2e209aaf903e50a1b0c 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_server.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/RPC_server.mli @@ -23,13 +23,4 @@ (* *) (*****************************************************************************) -open Tezos_rpc_http_server - -(** [start node_ctxt config] starts an RPC server listening for requests on the - port [config.rpc_port] and address [config.rpc_addr]. *) -val start : - Node_context.rw -> Configuration.t -> RPC_server.server tzresult Lwt.t - -(** Shutdown a running RPC server. When this function is called, the rollup node - will stop listening to incoming requests. *) -val shutdown : RPC_server.server -> unit Lwt.t +include Daemon_components.RPC_server_sig diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/batcher.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/batcher.mli index f4e9e223a647d95cd91514b1d49100f400a6ebac..f38610bade8e27745ce4bdab2d7f0bfdb09ce572 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/batcher.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/batcher.mli @@ -23,8 +23,7 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context +include Daemon_components.Batcher_sig (** The type for the status of messages in the batcher. *) type status = @@ -33,15 +32,6 @@ type status = (** The message has already been batched and sent to the injector in an L1 operation whose hash is given. *) -(** [init config ~signer node_ctxt] initializes and starts the batcher for - [signer]. If [config.simulation] is [true] (the default), messages added to - the batcher are simulated in an incremental simulation context. *) -val init : - Configuration.batcher -> - signer:public_key_hash -> - _ Node_context.t -> - unit tzresult Lwt.t - (** Return [true] if the batcher was started for this node. *) val active : unit -> bool @@ -59,17 +49,6 @@ val get_queue : unit -> (L2_message.hash * L2_message.t) list tzresult are not queued. *) val register_messages : string list -> L2_message.hash list tzresult Lwt.t -(** Create L2 batches of operations from the queue and pack them in an L1 batch - operation. The batch operation is queued in the injector for injection on - the Tezos node. *) -val batch : unit -> unit tzresult Lwt.t - -(** Notify a new L2 head to the batcher worker. *) -val new_head : Layer1.head -> unit tzresult Lwt.t - -(** Shutdown the batcher, waiting for the ongoing request to be processed. *) -val shutdown : unit -> unit Lwt.t - (** The status of a message in the batcher. Returns [None] if the message is not known by the batcher (the batcher only keeps the batched status of the last 500000 messages). *) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml index d6ea37809f74a18a4a8ab2143628ed6f98ed3d5e..7782ae1722f451cb094ea1ab8e8215979a17be60 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon.ml @@ -330,8 +330,8 @@ let exit_after_proto_migration node_ctxt ?predecessor head = let*! _ = Lwt_exit.exit_and_wait 0 in return_unit -let rec process_head (node_ctxt : _ Node_context.t) ~catching_up - (head : Layer1.header) = +let rec process_head (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) ~catching_up (head : Layer1.header) = let open Lwt_result_syntax in let start_timestamp = Time.System.now () in let* already_processed = Node_context.is_processed node_ctxt head.hash in @@ -345,7 +345,9 @@ let rec process_head (node_ctxt : _ Node_context.t) ~catching_up return_unit | Some predecessor -> let* () = exit_on_other_proto node_ctxt ~predecessor head in - let* () = process_head node_ctxt ~catching_up:true predecessor in + let* () = + process_head daemon_components node_ctxt ~catching_up:true predecessor + in let* ctxt = previous_context node_ctxt ~predecessor in let* () = Node_context.save_level @@ -419,8 +421,10 @@ let rec process_head (node_ctxt : _ Node_context.t) ~catching_up (* [on_layer_1_head node_ctxt head] processes a new head from the L1. It also processes any missing blocks that were not processed. *) -let on_layer_1_head node_ctxt (head : Layer1.header) = +let on_layer_1_head (daemon_components : (module Daemon_components.S)) node_ctxt + (head : Layer1.header) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let* old_head = Node_context.last_processed_head_opt node_ctxt in let old_head = match old_head with @@ -479,28 +483,33 @@ let on_layer_1_head node_ctxt (head : Layer1.header) = Layer1.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; let* header = get_header block in let catching_up = block.level < head.level in - process_head node_ctxt ~catching_up header) + process_head daemon_components node_ctxt ~catching_up header) new_chain_prefetching in let* () = Publisher.publish_commitments () in let* () = Publisher.cement_commitments () in let*! () = Daemon_event.new_heads_processed reorg.new_chain in let* () = Refutation_coordinator.process stripped_head in - let* () = Batcher.batch () in - let* () = Batcher.new_head stripped_head in + let* () = Components.Batcher.batch () in + let* () = Components.Batcher.new_head stripped_head in let*! () = Injector.inject ~header:head.header () in let* () = exit_after_proto_migration node_ctxt head in return_unit -let daemonize (node_ctxt : _ Node_context.t) = - Layer1.iter_heads node_ctxt.l1_ctxt (on_layer_1_head node_ctxt) +let daemonize (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) = + Layer1.iter_heads + node_ctxt.l1_ctxt + (on_layer_1_head daemon_components node_ctxt) -let degraded_refutation_mode (node_ctxt : _ Node_context.t) = +let degraded_refutation_mode (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let*! () = Daemon_event.degraded_mode () in let message = node_ctxt.Node_context.cctxt#message in let*! () = message "Shutting down Batcher@." in - let*! () = Batcher.shutdown () in + let*! () = Components.Batcher.shutdown () in let*! () = message "Shutting down Commitment Publisher@." in let*! () = Publisher.shutdown () in Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> @@ -509,16 +518,18 @@ let degraded_refutation_mode (node_ctxt : _ Node_context.t) = let* () = exit_on_other_proto node_ctxt head in return_unit -let install_finalizer node_ctxt rpc_server = +let install_finalizer (daemon_components : (module Daemon_components.S)) + node_ctxt rpc_server = let open Lwt_syntax in + let (module Components) = daemon_components in Lwt_exit.register_clean_up_callback ~loc:__LOC__ @@ fun exit_status -> let message = node_ctxt.Node_context.cctxt#message in let* () = message "Shutting down RPC server@." in - let* () = RPC_server.shutdown rpc_server in + let* () = Components.RPC_server.shutdown rpc_server in let* () = message "Shutting down Injector@." in let* () = Injector.shutdown () in let* () = message "Shutting down Batcher@." in - let* () = Batcher.shutdown () in + let* () = Components.Batcher.shutdown () in let* () = message "Shutting down Commitment Publisher@." in let* () = Publisher.shutdown () in let* () = message "Shutting down Refutation Coordinator@." in @@ -547,12 +558,14 @@ let check_initial_state_hash {Node_context.cctxt; rollup_address; pvm; _} = expected_state_hash = l1_reference_initial_state_hash; }) -let run node_ctxt configuration = +let run node_ctxt configuration + (daemon_components : (module Daemon_components.S)) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let* () = check_initial_state_hash node_ctxt in let* rpc_server = RPC_server.start node_ctxt configuration in let (_ : Lwt_exit.clean_up_callback_id) = - install_finalizer node_ctxt rpc_server + install_finalizer daemon_components node_ctxt rpc_server in let start () = let*! () = Inbox.start () in @@ -598,7 +611,8 @@ let run node_ctxt configuration = Configuration.Operator_purpose_map.find Add_messages node_ctxt.operators with | None -> return_unit - | Some signer -> Batcher.init configuration.batcher ~signer node_ctxt + | Some signer -> + Components.Batcher.init configuration.batcher ~signer node_ctxt in Lwt.dont_wait (fun () -> @@ -614,7 +628,7 @@ let run node_ctxt configuration = ~rpc_addr:configuration.rpc_addr ~rpc_port:configuration.rpc_port in - daemonize node_ctxt + daemonize daemon_components node_ctxt in Metrics.Info.init_rollup_node_info ~id:configuration.sc_rollup_address @@ -629,7 +643,7 @@ let run node_ctxt configuration = return_unit | e -> let*! () = Daemon_event.error e in - degraded_refutation_mode node_ctxt) + degraded_refutation_mode daemon_components node_ctxt) module Internal_for_tests = struct (** Same as {!process_head} but only builds and stores the L2 block @@ -687,8 +701,15 @@ module Internal_for_tests = struct return l2_block end -let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) - (cctxt : Protocol_client_context.full) = +module Rollup_node_daemon_components : Daemon_components.S = struct + module Batcher = Batcher + module RPC_server = RPC_server +end + +let run + ?(daemon_components : (module Daemon_components.S) = + (module Rollup_node_daemon_components)) ~data_dir ?log_kernel_debug_file + (configuration : Configuration.t) (cctxt : Protocol_client_context.full) = let open Lwt_result_syntax in Random.self_init () (* Initialize random state (for reconnection delays) *) ; let*! () = Event.starting_node () in @@ -726,4 +747,4 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) ~proto_level:predecessor.proto_level configuration in - run node_ctxt configuration + run node_ctxt configuration daemon_components diff --git a/src/lib_scoru_sequencer/configuration.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon_components.ml similarity index 52% rename from src/lib_scoru_sequencer/configuration.mli rename to src/proto_016_PtMumbai/lib_sc_rollup_node/daemon_components.ml index cc358b05a3323698e2ec550492cf96aeee5b626f..8b951410f4faafc20bc2a7a069f2955729bd0d5c 100644 --- a/src/lib_scoru_sequencer/configuration.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/daemon_components.ml @@ -1,8 +1,9 @@ (*****************************************************************************) (* *) (* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* Copyright (c) 2022-2023 TriliTech *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) (* *) (* Permission is hereby granted, free of charge, to any person obtaining a *) (* copy of this software and associated documentation files (the "Software"),*) @@ -24,4 +25,46 @@ (* *) (*****************************************************************************) -type t = {rpc_addr : string; rpc_port : int} +open Protocol +open Alpha_context + +module type Batcher_sig = sig + (** [init config ~signer node_ctxt] initializes and starts the batcher for + [signer]. If [config.simulation] is [true] (the default), messages added to + the batcher are simulated in an incremental simulation context. *) + val init : + Configuration.batcher -> + signer:public_key_hash -> + _ Node_context.t -> + unit tzresult Lwt.t + + (** Create L2 batches of operations from the queue and pack them in an L1 batch + operation. The batch operation is queued in the injector for injection on + the Tezos node. *) + val batch : unit -> unit tzresult Lwt.t + + (** Notify a new L2 head to the batcher worker. *) + val new_head : Layer1.head -> unit tzresult Lwt.t + + (** Shutdown the batcher, waiting for the ongoing request to be processed. *) + val shutdown : unit -> unit Lwt.t +end + +module type RPC_server_sig = sig + (** [start node_ctxt config] starts an RPC server listening for requests on + the port [config.rpc_port] and address [config.rpc_addr]. *) + val start : + Node_context.rw -> + Configuration.t -> + Tezos_rpc_http_server.RPC_server.server tzresult Lwt.t + + (** Shutdown a running RPC server. When this function is called, the rollup + node will stop listening to incoming requests. *) + val shutdown : Tezos_rpc_http_server.RPC_server.server -> unit Lwt.t +end + +module type S = sig + module Batcher : Batcher_sig + + module RPC_server : RPC_server_sig +end diff --git a/src/proto_017_PtNairob/bin_sc_rollup_node/main_sc_rollup_node_017_PtNairob.ml b/src/proto_017_PtNairob/bin_sc_rollup_node/main_sc_rollup_node_017_PtNairob.ml index 43cf6f4451fb73ef31851de8122ca654fbfe3c9d..1f0e328c8b07d10966c9bab474aa072c7c468c2d 100644 --- a/src/proto_017_PtNairob/bin_sc_rollup_node/main_sc_rollup_node_017_PtNairob.ml +++ b/src/proto_017_PtNairob/bin_sc_rollup_node/main_sc_rollup_node_017_PtNairob.ml @@ -24,6 +24,10 @@ (* *) (*****************************************************************************) +include Cli.Binary_dependent_args (struct + let binary_name = "smart rollup node" +end) + let group = { Tezos_clic.name = "sc_rollup.node"; diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_server.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_server.mli index 7830dad2505f33a4f67b31086d368c8c26e75514..6ce3fd2f3ec98de44ba3d2e209aaf903e50a1b0c 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_server.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/RPC_server.mli @@ -23,13 +23,4 @@ (* *) (*****************************************************************************) -open Tezos_rpc_http_server - -(** [start node_ctxt config] starts an RPC server listening for requests on the - port [config.rpc_port] and address [config.rpc_addr]. *) -val start : - Node_context.rw -> Configuration.t -> RPC_server.server tzresult Lwt.t - -(** Shutdown a running RPC server. When this function is called, the rollup node - will stop listening to incoming requests. *) -val shutdown : RPC_server.server -> unit Lwt.t +include Daemon_components.RPC_server_sig diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/batcher.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/batcher.mli index f4e9e223a647d95cd91514b1d49100f400a6ebac..f38610bade8e27745ce4bdab2d7f0bfdb09ce572 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/batcher.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/batcher.mli @@ -23,8 +23,7 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context +include Daemon_components.Batcher_sig (** The type for the status of messages in the batcher. *) type status = @@ -33,15 +32,6 @@ type status = (** The message has already been batched and sent to the injector in an L1 operation whose hash is given. *) -(** [init config ~signer node_ctxt] initializes and starts the batcher for - [signer]. If [config.simulation] is [true] (the default), messages added to - the batcher are simulated in an incremental simulation context. *) -val init : - Configuration.batcher -> - signer:public_key_hash -> - _ Node_context.t -> - unit tzresult Lwt.t - (** Return [true] if the batcher was started for this node. *) val active : unit -> bool @@ -59,17 +49,6 @@ val get_queue : unit -> (L2_message.hash * L2_message.t) list tzresult are not queued. *) val register_messages : string list -> L2_message.hash list tzresult Lwt.t -(** Create L2 batches of operations from the queue and pack them in an L1 batch - operation. The batch operation is queued in the injector for injection on - the Tezos node. *) -val batch : unit -> unit tzresult Lwt.t - -(** Notify a new L2 head to the batcher worker. *) -val new_head : Layer1.head -> unit tzresult Lwt.t - -(** Shutdown the batcher, waiting for the ongoing request to be processed. *) -val shutdown : unit -> unit Lwt.t - (** The status of a message in the batcher. Returns [None] if the message is not known by the batcher (the batcher only keeps the batched status of the last 500000 messages). *) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml index 0887106d956b88834f474530cdd6f0d65c3c43ee..1a80d45dfb07178880396d2918650fd8ed34638f 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon.ml @@ -328,8 +328,8 @@ let exit_after_proto_migration node_ctxt ?predecessor head = let*! _ = Lwt_exit.exit_and_wait 0 in return_unit -let rec process_head (node_ctxt : _ Node_context.t) ~catching_up - (head : Layer1.header) = +let rec process_head (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) ~catching_up (head : Layer1.header) = let open Lwt_result_syntax in let start_timestamp = Time.System.now () in let* already_processed = Node_context.is_processed node_ctxt head.hash in @@ -343,7 +343,9 @@ let rec process_head (node_ctxt : _ Node_context.t) ~catching_up return_unit | Some predecessor -> let* () = exit_on_other_proto node_ctxt ~predecessor head in - let* () = process_head node_ctxt ~catching_up:true predecessor in + let* () = + process_head daemon_components node_ctxt ~catching_up:true predecessor + in let* ctxt = previous_context node_ctxt ~predecessor in let* () = Node_context.save_level @@ -417,8 +419,10 @@ let rec process_head (node_ctxt : _ Node_context.t) ~catching_up (* [on_layer_1_head node_ctxt head] processes a new head from the L1. It also processes any missing blocks that were not processed. *) -let on_layer_1_head node_ctxt (head : Layer1.header) = +let on_layer_1_head (daemon_components : (module Daemon_components.S)) node_ctxt + (head : Layer1.header) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let* old_head = Node_context.last_processed_head_opt node_ctxt in let old_head = match old_head with @@ -477,28 +481,33 @@ let on_layer_1_head node_ctxt (head : Layer1.header) = Layer1.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; let* header = get_header block in let catching_up = block.level < head.level in - process_head node_ctxt ~catching_up header) + process_head daemon_components node_ctxt ~catching_up header) new_chain_prefetching in let* () = Publisher.publish_commitments () in let* () = Publisher.cement_commitments () in let*! () = Daemon_event.new_heads_processed reorg.new_chain in let* () = Refutation_coordinator.process stripped_head in - let* () = Batcher.batch () in - let* () = Batcher.new_head stripped_head in + let* () = Components.Batcher.batch () in + let* () = Components.Batcher.new_head stripped_head in let*! () = Injector.inject ~header:head.header () in let* () = exit_after_proto_migration node_ctxt head in return_unit -let daemonize (node_ctxt : _ Node_context.t) = - Layer1.iter_heads node_ctxt.l1_ctxt (on_layer_1_head node_ctxt) +let daemonize (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) = + Layer1.iter_heads + node_ctxt.l1_ctxt + (on_layer_1_head daemon_components node_ctxt) -let degraded_refutation_mode (node_ctxt : _ Node_context.t) = +let degraded_refutation_mode (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let*! () = Daemon_event.degraded_mode () in let message = node_ctxt.Node_context.cctxt#message in let*! () = message "Shutting down Batcher@." in - let*! () = Batcher.shutdown () in + let*! () = Components.Batcher.shutdown () in let*! () = message "Shutting down Commitment Publisher@." in let*! () = Publisher.shutdown () in Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> @@ -507,16 +516,18 @@ let degraded_refutation_mode (node_ctxt : _ Node_context.t) = let* () = exit_on_other_proto node_ctxt head in return_unit -let install_finalizer node_ctxt rpc_server = +let install_finalizer (daemon_components : (module Daemon_components.S)) + node_ctxt rpc_server = let open Lwt_syntax in + let (module Components) = daemon_components in Lwt_exit.register_clean_up_callback ~loc:__LOC__ @@ fun exit_status -> let message = node_ctxt.Node_context.cctxt#message in let* () = message "Shutting down RPC server@." in - let* () = RPC_server.shutdown rpc_server in + let* () = Components.RPC_server.shutdown rpc_server in let* () = message "Shutting down Injector@." in let* () = Injector.shutdown () in let* () = message "Shutting down Batcher@." in - let* () = Batcher.shutdown () in + let* () = Components.Batcher.shutdown () in let* () = message "Shutting down Commitment Publisher@." in let* () = Publisher.shutdown () in let* () = message "Shutting down Refutation Coordinator@." in @@ -545,12 +556,14 @@ let check_initial_state_hash {Node_context.cctxt; rollup_address; pvm; _} = expected_state_hash = l1_reference_initial_state_hash; }) -let run node_ctxt configuration = +let run node_ctxt configuration + (daemon_components : (module Daemon_components.S)) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let* () = check_initial_state_hash node_ctxt in let* rpc_server = RPC_server.start node_ctxt configuration in let (_ : Lwt_exit.clean_up_callback_id) = - install_finalizer node_ctxt rpc_server + install_finalizer daemon_components node_ctxt rpc_server in let start () = let*! () = Inbox.start () in @@ -591,7 +604,8 @@ let run node_ctxt configuration = Configuration.Operator_purpose_map.find Add_messages node_ctxt.operators with | None -> return_unit - | Some signer -> Batcher.init configuration.batcher ~signer node_ctxt + | Some signer -> + Components.Batcher.init configuration.batcher ~signer node_ctxt in Lwt.dont_wait (fun () -> @@ -607,7 +621,7 @@ let run node_ctxt configuration = ~rpc_addr:configuration.rpc_addr ~rpc_port:configuration.rpc_port in - daemonize node_ctxt + daemonize daemon_components node_ctxt in Metrics.Info.init_rollup_node_info ~id:configuration.sc_rollup_address @@ -622,7 +636,7 @@ let run node_ctxt configuration = return_unit | e -> let*! () = Daemon_event.error e in - degraded_refutation_mode node_ctxt) + degraded_refutation_mode daemon_components node_ctxt) module Internal_for_tests = struct (** Same as {!process_head} but only builds and stores the L2 block @@ -681,8 +695,15 @@ module Internal_for_tests = struct return l2_block end -let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) - (cctxt : Protocol_client_context.full) = +module Rollup_node_daemon_components : Daemon_components.S = struct + module Batcher = Batcher + module RPC_server = RPC_server +end + +let run + ?(daemon_components : (module Daemon_components.S) = + (module Rollup_node_daemon_components)) ~data_dir ?log_kernel_debug_file + (configuration : Configuration.t) (cctxt : Protocol_client_context.full) = let open Lwt_result_syntax in Random.self_init () (* Initialize random state (for reconnection delays) *) ; let*! () = Event.starting_node () in @@ -720,4 +741,4 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) ~proto_level:predecessor.proto_level configuration in - run node_ctxt configuration + run node_ctxt configuration daemon_components diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/daemon_components.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon_components.ml new file mode 100644 index 0000000000000000000000000000000000000000..8b951410f4faafc20bc2a7a069f2955729bd0d5c --- /dev/null +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/daemon_components.ml @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module type Batcher_sig = sig + (** [init config ~signer node_ctxt] initializes and starts the batcher for + [signer]. If [config.simulation] is [true] (the default), messages added to + the batcher are simulated in an incremental simulation context. *) + val init : + Configuration.batcher -> + signer:public_key_hash -> + _ Node_context.t -> + unit tzresult Lwt.t + + (** Create L2 batches of operations from the queue and pack them in an L1 batch + operation. The batch operation is queued in the injector for injection on + the Tezos node. *) + val batch : unit -> unit tzresult Lwt.t + + (** Notify a new L2 head to the batcher worker. *) + val new_head : Layer1.head -> unit tzresult Lwt.t + + (** Shutdown the batcher, waiting for the ongoing request to be processed. *) + val shutdown : unit -> unit Lwt.t +end + +module type RPC_server_sig = sig + (** [start node_ctxt config] starts an RPC server listening for requests on + the port [config.rpc_port] and address [config.rpc_addr]. *) + val start : + Node_context.rw -> + Configuration.t -> + Tezos_rpc_http_server.RPC_server.server tzresult Lwt.t + + (** Shutdown a running RPC server. When this function is called, the rollup + node will stop listening to incoming requests. *) + val shutdown : Tezos_rpc_http_server.RPC_server.server -> unit Lwt.t +end + +module type S = sig + module Batcher : Batcher_sig + + module RPC_server : RPC_server_sig +end diff --git a/src/proto_alpha/bin_sc_rollup_node/main_sc_rollup_node_alpha.ml b/src/proto_alpha/bin_sc_rollup_node/main_sc_rollup_node_alpha.ml index 6ddfaee0784c764f6f3b4d734c7d377a9ff93c3d..eb99a13743eec03935c078fb2178a28ce3a36d3e 100644 --- a/src/proto_alpha/bin_sc_rollup_node/main_sc_rollup_node_alpha.ml +++ b/src/proto_alpha/bin_sc_rollup_node/main_sc_rollup_node_alpha.ml @@ -24,6 +24,10 @@ (* *) (*****************************************************************************) +include Cli.Binary_dependent_args (struct + let binary_name = "smart rollup node" +end) + let group = { Tezos_clic.name = "sc_rollup.node"; diff --git a/src/proto_alpha/lib_sc_rollup_node/RPC_server.mli b/src/proto_alpha/lib_sc_rollup_node/RPC_server.mli index 7830dad2505f33a4f67b31086d368c8c26e75514..6ce3fd2f3ec98de44ba3d2e209aaf903e50a1b0c 100644 --- a/src/proto_alpha/lib_sc_rollup_node/RPC_server.mli +++ b/src/proto_alpha/lib_sc_rollup_node/RPC_server.mli @@ -23,13 +23,4 @@ (* *) (*****************************************************************************) -open Tezos_rpc_http_server - -(** [start node_ctxt config] starts an RPC server listening for requests on the - port [config.rpc_port] and address [config.rpc_addr]. *) -val start : - Node_context.rw -> Configuration.t -> RPC_server.server tzresult Lwt.t - -(** Shutdown a running RPC server. When this function is called, the rollup node - will stop listening to incoming requests. *) -val shutdown : RPC_server.server -> unit Lwt.t +include Daemon_components.RPC_server_sig diff --git a/src/proto_alpha/lib_sc_rollup_node/batcher.mli b/src/proto_alpha/lib_sc_rollup_node/batcher.mli index f4e9e223a647d95cd91514b1d49100f400a6ebac..f38610bade8e27745ce4bdab2d7f0bfdb09ce572 100644 --- a/src/proto_alpha/lib_sc_rollup_node/batcher.mli +++ b/src/proto_alpha/lib_sc_rollup_node/batcher.mli @@ -23,8 +23,7 @@ (* *) (*****************************************************************************) -open Protocol -open Alpha_context +include Daemon_components.Batcher_sig (** The type for the status of messages in the batcher. *) type status = @@ -33,15 +32,6 @@ type status = (** The message has already been batched and sent to the injector in an L1 operation whose hash is given. *) -(** [init config ~signer node_ctxt] initializes and starts the batcher for - [signer]. If [config.simulation] is [true] (the default), messages added to - the batcher are simulated in an incremental simulation context. *) -val init : - Configuration.batcher -> - signer:public_key_hash -> - _ Node_context.t -> - unit tzresult Lwt.t - (** Return [true] if the batcher was started for this node. *) val active : unit -> bool @@ -59,17 +49,6 @@ val get_queue : unit -> (L2_message.hash * L2_message.t) list tzresult are not queued. *) val register_messages : string list -> L2_message.hash list tzresult Lwt.t -(** Create L2 batches of operations from the queue and pack them in an L1 batch - operation. The batch operation is queued in the injector for injection on - the Tezos node. *) -val batch : unit -> unit tzresult Lwt.t - -(** Notify a new L2 head to the batcher worker. *) -val new_head : Layer1.head -> unit tzresult Lwt.t - -(** Shutdown the batcher, waiting for the ongoing request to be processed. *) -val shutdown : unit -> unit Lwt.t - (** The status of a message in the batcher. Returns [None] if the message is not known by the batcher (the batcher only keeps the batched status of the last 500000 messages). *) diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon.ml b/src/proto_alpha/lib_sc_rollup_node/daemon.ml index b36b978023914c7dcc1b7f081262dcddbcdf14a4..210ecfdbb4a534eb6679b3e0266f3bfe87fe53ec 100644 --- a/src/proto_alpha/lib_sc_rollup_node/daemon.ml +++ b/src/proto_alpha/lib_sc_rollup_node/daemon.ml @@ -328,8 +328,8 @@ let exit_after_proto_migration node_ctxt ?predecessor head = let*! _ = Lwt_exit.exit_and_wait 0 in return_unit -let rec process_head (node_ctxt : _ Node_context.t) ~catching_up - (head : Layer1.header) = +let rec process_head (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) ~catching_up (head : Layer1.header) = let open Lwt_result_syntax in let start_timestamp = Time.System.now () in let* already_processed = Node_context.is_processed node_ctxt head.hash in @@ -343,7 +343,9 @@ let rec process_head (node_ctxt : _ Node_context.t) ~catching_up return_unit | Some predecessor -> let* () = exit_on_other_proto node_ctxt ~predecessor head in - let* () = process_head node_ctxt ~catching_up:true predecessor in + let* () = + process_head daemon_components node_ctxt ~catching_up:true predecessor + in let* ctxt = previous_context node_ctxt ~predecessor in let* () = Node_context.save_level @@ -417,8 +419,10 @@ let rec process_head (node_ctxt : _ Node_context.t) ~catching_up (* [on_layer_1_head node_ctxt head] processes a new head from the L1. It also processes any missing blocks that were not processed. *) -let on_layer_1_head node_ctxt (head : Layer1.header) = +let on_layer_1_head (daemon_components : (module Daemon_components.S)) node_ctxt + (head : Layer1.header) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let* old_head = Node_context.last_processed_head_opt node_ctxt in let old_head = match old_head with @@ -477,28 +481,33 @@ let on_layer_1_head node_ctxt (head : Layer1.header) = Layer1.prefetch_tezos_blocks node_ctxt.l1_ctxt to_prefetch ; let* header = get_header block in let catching_up = block.level < head.level in - process_head node_ctxt ~catching_up header) + process_head daemon_components node_ctxt ~catching_up header) new_chain_prefetching in let* () = Publisher.publish_commitments () in let* () = Publisher.cement_commitments () in let*! () = Daemon_event.new_heads_processed reorg.new_chain in let* () = Refutation_coordinator.process stripped_head in - let* () = Batcher.batch () in - let* () = Batcher.new_head stripped_head in + let* () = Components.Batcher.batch () in + let* () = Components.Batcher.new_head stripped_head in let*! () = Injector.inject ~header:head.header () in let* () = exit_after_proto_migration node_ctxt head in return_unit -let daemonize (node_ctxt : _ Node_context.t) = - Layer1.iter_heads node_ctxt.l1_ctxt (on_layer_1_head node_ctxt) +let daemonize (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) = + Layer1.iter_heads + node_ctxt.l1_ctxt + (on_layer_1_head daemon_components node_ctxt) -let degraded_refutation_mode (node_ctxt : _ Node_context.t) = +let degraded_refutation_mode (daemon_components : (module Daemon_components.S)) + (node_ctxt : _ Node_context.t) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let*! () = Daemon_event.degraded_mode () in let message = node_ctxt.Node_context.cctxt#message in let*! () = message "Shutting down Batcher@." in - let*! () = Batcher.shutdown () in + let*! () = Components.Batcher.shutdown () in let*! () = message "Shutting down Commitment Publisher@." in let*! () = Publisher.shutdown () in Layer1.iter_heads node_ctxt.l1_ctxt @@ fun head -> @@ -507,16 +516,18 @@ let degraded_refutation_mode (node_ctxt : _ Node_context.t) = let* () = exit_on_other_proto node_ctxt head in return_unit -let install_finalizer node_ctxt rpc_server = +let install_finalizer (daemon_components : (module Daemon_components.S)) + node_ctxt rpc_server = let open Lwt_syntax in + let (module Components) = daemon_components in Lwt_exit.register_clean_up_callback ~loc:__LOC__ @@ fun exit_status -> let message = node_ctxt.Node_context.cctxt#message in let* () = message "Shutting down RPC server@." in - let* () = RPC_server.shutdown rpc_server in + let* () = Components.RPC_server.shutdown rpc_server in let* () = message "Shutting down Injector@." in let* () = Injector.shutdown () in let* () = message "Shutting down Batcher@." in - let* () = Batcher.shutdown () in + let* () = Components.Batcher.shutdown () in let* () = message "Shutting down Commitment Publisher@." in let* () = Publisher.shutdown () in let* () = message "Shutting down Refutation Coordinator@." in @@ -545,12 +556,14 @@ let check_initial_state_hash {Node_context.cctxt; rollup_address; pvm; _} = expected_state_hash = l1_reference_initial_state_hash; }) -let run node_ctxt configuration = +let run node_ctxt configuration + (daemon_components : (module Daemon_components.S)) = let open Lwt_result_syntax in + let (module Components) = daemon_components in let* () = check_initial_state_hash node_ctxt in let* rpc_server = RPC_server.start node_ctxt configuration in let (_ : Lwt_exit.clean_up_callback_id) = - install_finalizer node_ctxt rpc_server + install_finalizer daemon_components node_ctxt rpc_server in let start () = let*! () = Inbox.start () in @@ -591,7 +604,8 @@ let run node_ctxt configuration = Configuration.Operator_purpose_map.find Add_messages node_ctxt.operators with | None -> return_unit - | Some signer -> Batcher.init configuration.batcher ~signer node_ctxt + | Some signer -> + Components.Batcher.init configuration.batcher ~signer node_ctxt in Lwt.dont_wait (fun () -> @@ -607,7 +621,7 @@ let run node_ctxt configuration = ~rpc_addr:configuration.rpc_addr ~rpc_port:configuration.rpc_port in - daemonize node_ctxt + daemonize daemon_components node_ctxt in Metrics.Info.init_rollup_node_info ~id:configuration.sc_rollup_address @@ -623,7 +637,7 @@ let run node_ctxt configuration = return_unit | e -> let*! () = Daemon_event.error e in - degraded_refutation_mode node_ctxt) + degraded_refutation_mode daemon_components node_ctxt) module Internal_for_tests = struct (** Same as {!process_head} but only builds and stores the L2 block @@ -682,8 +696,15 @@ module Internal_for_tests = struct return l2_block end -let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) - (cctxt : Protocol_client_context.full) = +module Rollup_node_daemon_components : Daemon_components.S = struct + module Batcher = Batcher + module RPC_server = RPC_server +end + +let run + ?(daemon_components : (module Daemon_components.S) = + (module Rollup_node_daemon_components)) ~data_dir ?log_kernel_debug_file + (configuration : Configuration.t) (cctxt : Protocol_client_context.full) = let open Lwt_result_syntax in Random.self_init () (* Initialize random state (for reconnection delays) *) ; let*! () = Event.starting_node () in @@ -721,4 +742,4 @@ let run ~data_dir ?log_kernel_debug_file (configuration : Configuration.t) ~proto_level:predecessor.proto_level configuration in - run node_ctxt configuration + run node_ctxt configuration daemon_components diff --git a/src/proto_alpha/lib_sc_rollup_node/daemon_components.ml b/src/proto_alpha/lib_sc_rollup_node/daemon_components.ml new file mode 100644 index 0000000000000000000000000000000000000000..8b951410f4faafc20bc2a7a069f2955729bd0d5c --- /dev/null +++ b/src/proto_alpha/lib_sc_rollup_node/daemon_components.ml @@ -0,0 +1,70 @@ +(*****************************************************************************) +(* *) +(* Open Source License *) +(* Copyright (c) 2023 Nomadic Labs, *) +(* Copyright (c) 2023 TriliTech *) +(* Copyright (c) 2023 Functori, *) +(* *) +(* Permission is hereby granted, free of charge, to any person obtaining a *) +(* copy of this software and associated documentation files (the "Software"),*) +(* to deal in the Software without restriction, including without limitation *) +(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *) +(* and/or sell copies of the Software, and to permit persons to whom the *) +(* Software is furnished to do so, subject to the following conditions: *) +(* *) +(* The above copyright notice and this permission notice shall be included *) +(* in all copies or substantial portions of the Software. *) +(* *) +(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*) +(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *) +(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *) +(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*) +(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *) +(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *) +(* DEALINGS IN THE SOFTWARE. *) +(* *) +(*****************************************************************************) + +open Protocol +open Alpha_context + +module type Batcher_sig = sig + (** [init config ~signer node_ctxt] initializes and starts the batcher for + [signer]. If [config.simulation] is [true] (the default), messages added to + the batcher are simulated in an incremental simulation context. *) + val init : + Configuration.batcher -> + signer:public_key_hash -> + _ Node_context.t -> + unit tzresult Lwt.t + + (** Create L2 batches of operations from the queue and pack them in an L1 batch + operation. The batch operation is queued in the injector for injection on + the Tezos node. *) + val batch : unit -> unit tzresult Lwt.t + + (** Notify a new L2 head to the batcher worker. *) + val new_head : Layer1.head -> unit tzresult Lwt.t + + (** Shutdown the batcher, waiting for the ongoing request to be processed. *) + val shutdown : unit -> unit Lwt.t +end + +module type RPC_server_sig = sig + (** [start node_ctxt config] starts an RPC server listening for requests on + the port [config.rpc_port] and address [config.rpc_addr]. *) + val start : + Node_context.rw -> + Configuration.t -> + Tezos_rpc_http_server.RPC_server.server tzresult Lwt.t + + (** Shutdown a running RPC server. When this function is called, the rollup + node will stop listening to incoming requests. *) + val shutdown : Tezos_rpc_http_server.RPC_server.server -> unit Lwt.t +end + +module type S = sig + module Batcher : Batcher_sig + + module RPC_server : RPC_server_sig +end