diff --git a/.gitlab/ci/jobs/packaging/opam_package.yml b/.gitlab/ci/jobs/packaging/opam_package.yml index d49aff55af933f1017ce14d034e5f324d57c4b62..d5e69c9f1915b348e46189b31932bbc7857b2751 100644 --- a/.gitlab/ci/jobs/packaging/opam_package.yml +++ b/.gitlab/ci/jobs/packaging/opam_package.yml @@ -392,6 +392,13 @@ opam:octez-smart-rollup-client-PtNairob: # Ignoring unreleased package octez-smart-rollup-client-alpha. +opam:octez-smart-rollup-node: + extends: + - .opam_template + - .rules_template__trigger_opam_batch_1 + variables: + package: octez-smart-rollup-node + opam:octez-smart-rollup-node-PtMumbai: extends: - .opam_template @@ -519,7 +526,7 @@ opam:tezos-base-test-helpers: opam:tezos-clic: extends: - .opam_template - - .rules_template__trigger_opam_batch_6 + - .rules_template__trigger_opam_batch_7 variables: package: tezos-clic @@ -673,7 +680,7 @@ opam:tezos-client-base-unix: opam:tezos-client-commands: extends: - .opam_template - - .rules_template__trigger_opam_batch_5 + - .rules_template__trigger_opam_batch_6 variables: package: tezos-client-commands @@ -687,7 +694,7 @@ opam:tezos-client-demo-counter: opam:tezos-client-genesis: extends: - .opam_template - - .rules_template__trigger_opam_batch_2 + - .rules_template__trigger_opam_batch_3 variables: package: tezos-client-genesis @@ -1018,7 +1025,7 @@ opam:tezos-mockup-commands: opam:tezos-mockup-proxy: extends: - .opam_template - - .rules_template__trigger_opam_batch_4 + - .rules_template__trigger_opam_batch_5 variables: package: tezos-mockup-proxy @@ -1264,7 +1271,7 @@ opam:tezos-protocol-plugin-009-PsFLoren: opam:tezos-protocol-plugin-009-PsFLoren-registerer: extends: - .opam_template - - .rules_template__trigger_opam_batch_1 + - .rules_template__trigger_opam_batch_2 variables: package: tezos-protocol-plugin-009-PsFLoren-registerer @@ -1387,7 +1394,7 @@ opam:tezos-protocol-plugin-017-PtNairob-registerer: opam:tezos-protocol-plugin-alpha: extends: - .opam_template - - .rules_template__trigger_opam_batch_3 + - .rules_template__trigger_opam_batch_4 variables: package: tezos-protocol-plugin-alpha diff --git a/dune-project b/dune-project index 064c16b951b11dfbe80d7d0286d8884a56b31608..4cd681b5d5c0ccc50f0ae2c7c8a536d6fc4dc2d1 100644 --- a/dune-project +++ b/dune-project @@ -37,6 +37,7 @@ (package (name octez-smart-rollup-client-PtMumbai)) (package (name octez-smart-rollup-client-PtNairob)) (package (name octez-smart-rollup-client-alpha)) +(package (name octez-smart-rollup-node)) (package (name octez-smart-rollup-node-PtMumbai)) (package (name octez-smart-rollup-node-PtNairob)) (package (name octez-smart-rollup-node-alpha)) diff --git a/manifest/main.ml b/manifest/main.ml index 40aae1664765608330669fcd79baf96f250fbdac..66a77cd3f0d7bdbbd859a344e277ebcd68f2355f 100644 --- a/manifest/main.ml +++ b/manifest/main.ml @@ -4098,6 +4098,20 @@ let octez_injector = octez_crawler |> open_; ] +let octez_smart_rollup_node_lib = + public_lib + "octez-smart-rollup-node" + ~path:"src/lib_smart_rollup_node" + ~synopsis:"Octez: library for Smart Rollup node" + ~deps: + [ + octez_base |> open_ ~m:"TzPervasives"; + octez_base_unix; + octez_stdlib_unix |> open_; + octez_crypto |> open_; + octez_injector |> open_; + ] + let octez_scoru_wasm_helpers = public_lib "tezos-scoru-wasm-helpers" @@ -6066,6 +6080,7 @@ let hash = Protocol.hash aches; aches_lwt; octez_injector |> open_; + octez_smart_rollup_node_lib |> open_; octez_scoru_wasm; octez_scoru_wasm_fast; octez_crypto_dal |> if_ N.(number >= 016) |> open_; @@ -6172,6 +6187,7 @@ let hash = Protocol.hash octez_client_base_unix |> open_; octez_client_commands |> open_; client |> if_some |> open_; + octez_smart_rollup_node_lib |> open_; octez_sc_rollup_node |> if_some |> open_; ] in diff --git a/opam/octez-smart-rollup-node-PtMumbai.opam b/opam/octez-smart-rollup-node-PtMumbai.opam index c0e3200f7cd300cd4474bf6b42a894cddc513c41..e7d9d46003725ef61e8d4517638130e0303931c5 100644 --- a/opam/octez-smart-rollup-node-PtMumbai.opam +++ b/opam/octez-smart-rollup-node-PtMumbai.opam @@ -37,6 +37,7 @@ depends: [ "aches" { >= "1.0.0" } "aches-lwt" { >= "1.0.0" } "octez-injector" + "octez-smart-rollup-node" "tezos-scoru-wasm" "tezos-scoru-wasm-fast" "tezos-crypto-dal" diff --git a/opam/octez-smart-rollup-node-PtNairob.opam b/opam/octez-smart-rollup-node-PtNairob.opam index ca4cd21382b0cda1140def877d1375a93f517a6f..2b966161c12d37a4a0d869c5a8a44aa1917b011d 100644 --- a/opam/octez-smart-rollup-node-PtNairob.opam +++ b/opam/octez-smart-rollup-node-PtNairob.opam @@ -37,6 +37,7 @@ depends: [ "aches" { >= "1.0.0" } "aches-lwt" { >= "1.0.0" } "octez-injector" + "octez-smart-rollup-node" "tezos-scoru-wasm" "tezos-scoru-wasm-fast" "tezos-crypto-dal" diff --git a/opam/octez-smart-rollup-node-alpha.opam b/opam/octez-smart-rollup-node-alpha.opam index 6a8fea0c85ff8c9404f9bfac4e0155823511b195..4175cf4fdcd03320d2a37f92b6d0930a9e2a2ebf 100644 --- a/opam/octez-smart-rollup-node-alpha.opam +++ b/opam/octez-smart-rollup-node-alpha.opam @@ -38,6 +38,7 @@ depends: [ "aches" { >= "1.0.0" } "aches-lwt" { >= "1.0.0" } "octez-injector" + "octez-smart-rollup-node" "tezos-scoru-wasm" "tezos-scoru-wasm-fast" "tezos-crypto-dal" diff --git a/opam/octez-smart-rollup-node.opam b/opam/octez-smart-rollup-node.opam new file mode 100644 index 0000000000000000000000000000000000000000..d3afa262e1ab7c73c91f474ee0817b6101649168 --- /dev/null +++ b/opam/octez-smart-rollup-node.opam @@ -0,0 +1,23 @@ +# 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-stdlib-unix" + "tezos-crypto" + "octez-injector" +] +build: [ + ["rm" "-r" "vendors"] + ["dune" "build" "-p" name "-j" jobs] + ["dune" "runtest" "-p" name "-j" jobs] {with-test} +] +synopsis: "Octez: library for Smart Rollup node" diff --git a/src/proto_alpha/lib_sc_rollup_node/configuration.ml b/src/lib_smart_rollup_node/configuration.ml similarity index 85% rename from src/proto_alpha/lib_sc_rollup_node/configuration.ml rename to src/lib_smart_rollup_node/configuration.ml index 90ea2170c7cf89ac93f21147b2d24bf219432aa2..e57e5e284534b0896372b7840f7f38e16bd9e4d5 100644 --- a/src/proto_alpha/lib_sc_rollup_node/configuration.ml +++ b/src/lib_smart_rollup_node/configuration.ml @@ -24,8 +24,6 @@ (* *) (*****************************************************************************) -open Protocol.Alpha_context - type mode = Observer | Accuser | Batcher | Maintenance | Operator | Custom type purpose = Publish | Add_messages | Cement | Timeout | Refute @@ -40,20 +38,20 @@ end) type operators = Signature.Public_key_hash.t Operator_purpose_map.t -type fee_parameters = Injection.fee_parameter Operator_purpose_map.t +type fee_parameters = Injector_sigs.fee_parameter Operator_purpose_map.t type batcher = { simulate : bool; min_batch_elements : int; min_batch_size : int; max_batch_elements : int; - max_batch_size : int; + max_batch_size : int option; } type injector = {retention_period : int; attempts : int; injection_ttl : int} type t = { - sc_rollup_address : Sc_rollup.t; + sc_rollup_address : Tezos_crypto.Hashed.Smart_rollup_address.t; boot_sector_file : string option; sc_rollup_node_operators : operators; rpc_addr : string; @@ -72,6 +70,33 @@ type t = { log_kernel_debug : bool; } +type error += + | Missing_mode_operators of {mode : string; missing_operators : string list} + +let () = + register_error_kind + ~id:"sc_rollup.node.missing_mode_operators" + ~title:"Missing operators for the chosen mode" + ~description:"Missing operators for the chosen mode." + ~pp:(fun ppf (mode, missing_operators) -> + Format.fprintf + ppf + "@[Missing operators %a for mode %s.@]" + (Format.pp_print_list + ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ") + Format.pp_print_string) + missing_operators + mode) + `Permanent + Data_encoding.( + obj2 (req "mode" string) (req "missing_operators" (list string))) + (function + | Missing_mode_operators {mode; missing_operators} -> + Some (mode, missing_operators) + | _ -> None) + (fun (mode, missing_operators) -> + Missing_mode_operators {mode; missing_operators}) + let default_data_dir = Filename.concat (Sys.getenv "HOME") ".tezos-smart-rollup-node" @@ -93,20 +118,23 @@ let default_metrics_port = 9933 let default_reconnection_delay = 2.0 (* seconds *) -let tez t = Tez.of_mutez_exn Int64.(mul (of_int t) 1_000_000L) +let mutez mutez = {Injector_sigs.mutez} + +let tez t = mutez Int64.(mul (of_int t) 1_000_000L) + +(* Copied from src/proto_alpha/lib_plugin/mempool.ml *) -let default_minimal_fees = Mempool.default_minimal_fees +let default_minimal_fees = mutez 100L -let default_minimal_nanotez_per_gas_unit = - Mempool.default_minimal_nanotez_per_gas_unit +let default_minimal_nanotez_per_gas_unit = Q.of_int 100 -let default_minimal_nanotez_per_byte = Mempool.default_minimal_nanotez_per_byte +let default_minimal_nanotez_per_byte = Q.of_int 1000 let default_force_low_fee = false let default_fee_cap = tez 1 -let default_burn_cap = Tez.zero +let default_burn_cap = mutez 0L (* The below default fee and burn limits are computed by taking into account the worst fee found in the tests for the rollup node. @@ -158,7 +186,7 @@ let default_fee_parameter ?purpose () = | Some purpose -> (default_fee purpose, default_burn purpose) in { - Injection.minimal_fees = default_minimal_fees; + Injector_sigs.minimal_fees = default_minimal_fees; minimal_nanotez_per_byte = default_minimal_nanotez_per_byte; minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit; force_low_fee = default_force_low_fee; @@ -181,45 +209,13 @@ let default_batcher_min_batch_size = 10 let default_batcher_max_batch_elements = max_int -let protocol_max_batch_size = - let empty_message_op : _ Operation.t = - let open Protocol in - let open Alpha_context in - let open Operation in - { - shell = {branch = Block_hash.zero}; - protocol_data = - { - signature = Some Signature.zero; - contents = - Single - (Manager_operation - { - source = Signature.Public_key_hash.zero; - fee = Tez.of_mutez_exn Int64.max_int; - counter = Manager_counter.Internal_for_tests.of_int max_int; - gas_limit = - Gas.Arith.integral_of_int_exn ((max_int - 1) / 1000); - storage_limit = Z.of_int max_int; - operation = Sc_rollup_add_messages {messages = [""]}; - }); - }; - } - in - Protocol.Constants_repr.max_operation_data_length - - Data_encoding.Binary.length - Operation.encoding_with_legacy_attestation_name - (Operation.pack empty_message_op) - -let default_batcher_max_batch_size = protocol_max_batch_size - let default_batcher = { simulate = default_batcher_simulate; min_batch_elements = default_batcher_min_batch_elements; min_batch_size = default_batcher_min_batch_size; max_batch_elements = default_batcher_max_batch_elements; - max_batch_size = default_batcher_max_batch_size; + max_batch_size = None; } let default_injector = @@ -325,11 +321,36 @@ let operator_purpose_map_encoding encoding = let operators_encoding = operator_purpose_map_encoding (fun _ -> Signature.Public_key_hash.encoding) +(* Encoding for Tez amounts, replicated from mempool. *) +let tez_encoding = + let open Data_encoding in + let decode {Injector_sigs.mutez} = Z.of_int64 mutez in + let encode = + Json.wrap_error (fun i -> {Injector_sigs.mutez = Z.to_int64 i}) + in + Data_encoding.def + "mutez" + ~title:"A millionth of a tez" + ~description:"One million mutez make a tez (1 tez = 1e6 mutez)" + (conv decode encode n) + +(* Encoding for nano-Tez amounts, replicated from mempool. *) +let nanotez_encoding = + let open Data_encoding in + def + "nanotez" + ~title:"A thousandth of a mutez" + ~description:"One thousand nanotez make a mutez (1 tez = 1e9 nanotez)" + (conv + (fun q -> (q.Q.num, q.Q.den)) + (fun (num, den) -> {Q.num; den}) + (tup2 z z)) + let fee_parameter_encoding purpose = let open Data_encoding in conv (fun { - Injection.minimal_fees; + Injector_sigs.minimal_fees; minimal_nanotez_per_byte; minimal_nanotez_per_gas_unit; force_low_fee; @@ -360,17 +381,17 @@ let fee_parameter_encoding purpose = (dft "minimal-fees" ~description:"Exclude operations with lower fees" - Tez.encoding + tez_encoding default_minimal_fees) (dft "minimal-nanotez-per-byte" ~description:"Exclude operations with lower fees per byte" - Plugin.Mempool.nanotez_enc + nanotez_encoding default_minimal_nanotez_per_byte) (dft "minimal-nanotez-per-gas-unit" ~description:"Exclude operations with lower gas fees" - Plugin.Mempool.nanotez_enc + nanotez_encoding default_minimal_nanotez_per_gas_unit) (dft "force-low-fee" @@ -381,12 +402,12 @@ let fee_parameter_encoding purpose = (dft "fee-cap" ~description:"The fee cap" - Tez.encoding + tez_encoding (default_fee purpose)) (dft "burn-cap" ~description:"The burn cap" - Tez.encoding + tez_encoding (default_burn purpose))) let fee_parameters_encoding = @@ -454,33 +475,38 @@ let batcher_encoding = min_batch_size, max_batch_elements, max_batch_size ) -> - if max_batch_size > protocol_max_batch_size then - Error - (Format.sprintf - "max_batch_size must be smaller than %d" - protocol_max_batch_size) - else if min_batch_size <= 0 then Error "min_batch_size must be positive" - else if max_batch_size < min_batch_size then - Error "max_batch_size must be greater than min_batch_size" - else if min_batch_elements <= 0 then - Error "min_batch_elements must be positive" - else if max_batch_elements < min_batch_elements then - Error "max_batch_elements must be greater than min_batch_elements" - else - Ok - { - simulate; - min_batch_elements; - min_batch_size; - max_batch_elements; - max_batch_size; - }) + let open Result_syntax in + let error_when c s = if c then Error s else return_unit in + let* () = + error_when (min_batch_size <= 0) "min_batch_size must be positive" + in + let* () = + match max_batch_size with + | Some m when m < min_batch_size -> + Error "max_batch_size must be greater than min_batch_size" + | _ -> return_unit + in + let* () = + error_when (min_batch_elements <= 0) "min_batch_size must be positive" + in + let+ () = + error_when + (max_batch_elements < min_batch_elements) + "max_batch_elements must be greater than min_batch_elements" + in + { + simulate; + min_batch_elements; + min_batch_size; + max_batch_elements; + max_batch_size; + }) @@ obj5 (dft "simulate" bool default_batcher_simulate) (dft "min_batch_elements" int31 default_batcher_min_batch_elements) (dft "min_batch_size" int31 default_batcher_min_batch_size) (dft "max_batch_elements" int31 default_batcher_max_batch_elements) - (dft "max_batch_size" int31 default_batcher_max_batch_size) + (opt "max_batch_size" int31) let injector_encoding : injector Data_encoding.t = let open Data_encoding in @@ -581,7 +607,7 @@ let encoding : t Data_encoding.t = (req "smart-rollup-address" ~description:"Smart rollup address" - Protocol.Alpha_context.Sc_rollup.Address.encoding) + Tezos_crypto.Hashed.Smart_rollup_address.encoding) (opt "boot-sector" ~description:"Boot sector" string) (req "smart-rollup-node-operator" @@ -636,8 +662,7 @@ let check_mode config = if missing_operators <> [] then let mode = string_of_mode config.mode in let missing_operators = List.map string_of_purpose missing_operators in - tzfail - (Sc_rollup_node_errors.Missing_mode_operators {mode; missing_operators}) + tzfail (Missing_mode_operators {mode; missing_operators}) else return_unit in let narrow_purposes purposes = diff --git a/src/proto_alpha/lib_sc_rollup_node/configuration.mli b/src/lib_smart_rollup_node/configuration.mli similarity index 95% rename from src/proto_alpha/lib_sc_rollup_node/configuration.mli rename to src/lib_smart_rollup_node/configuration.mli index 28a444922e769df374cd5ec468b2130852ff880f..bb8180fd0bc279b838f0afdc8e10a4aab36cb7f3 100644 --- a/src/proto_alpha/lib_sc_rollup_node/configuration.mli +++ b/src/lib_smart_rollup_node/configuration.mli @@ -43,7 +43,7 @@ module Operator_purpose_map : Map.S with type key = purpose type operators = Signature.Public_key_hash.t Operator_purpose_map.t -type fee_parameters = Injection.fee_parameter Operator_purpose_map.t +type fee_parameters = Injector_sigs.fee_parameter Operator_purpose_map.t (** Configuration for the batcher. @@ -54,7 +54,7 @@ type fee_parameters = Injection.fee_parameter Operator_purpose_map.t type batcher = { simulate : bool; (** If [true], the batcher will simulate the messages it receives, in an - incremental context, before queuing them. *) + incremental context, before queuing them. *) min_batch_elements : int; (** The minimum number elements in a batch for it to be produced when the batcher receives new messages. *) @@ -63,7 +63,7 @@ type batcher = { batcher receives new messages. *) max_batch_elements : int; (** The maximum number of elements that we can put in a batch. *) - max_batch_size : int; (** The maximum size in bytes of a batch. *) + max_batch_size : int option; (** The maximum size in bytes of a batch. *) } type injector = { @@ -78,7 +78,7 @@ type injector = { } type t = { - sc_rollup_address : Protocol.Alpha_context.Sc_rollup.t; + sc_rollup_address : Tezos_crypto.Hashed.Smart_rollup_address.t; boot_sector_file : string option; sc_rollup_node_operators : operators; rpc_addr : string; @@ -141,7 +141,8 @@ val default_reconnection_delay : float (** [default_fee_parameter ?purpose ()] is the default fee parameter to inject operation on L1. If [purpose] is provided, it returns the default fee parameter for the specific purpose. *) -val default_fee_parameter : ?purpose:purpose -> unit -> Injection.fee_parameter +val default_fee_parameter : + ?purpose:purpose -> unit -> Injector_sigs.fee_parameter (** [default_fee_parameters] is the default fee parameters configuration build with {!default_fee_parameter} for all purposes. *) diff --git a/src/lib_smart_rollup_node/dune b/src/lib_smart_rollup_node/dune new file mode 100644 index 0000000000000000000000000000000000000000..ccb262db751e7b6f7442933aaa171ba16b3b5d42 --- /dev/null +++ b/src/lib_smart_rollup_node/dune @@ -0,0 +1,19 @@ +; This file was automatically generated, do not edit. +; Edit file manifest/main.ml instead. + +(library + (name octez_smart_rollup_node) + (public_name octez-smart-rollup-node) + (instrumentation (backend bisect_ppx)) + (libraries + tezos-base + tezos-base.unix + tezos-stdlib-unix + tezos-crypto + octez-injector) + (flags + (:standard) + -open Tezos_base.TzPervasives + -open Tezos_stdlib_unix + -open Tezos_crypto + -open Octez_injector)) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/loser_mode.ml b/src/lib_smart_rollup_node/loser_mode.ml similarity index 100% rename from src/proto_016_PtMumbai/lib_sc_rollup_node/loser_mode.ml rename to src/lib_smart_rollup_node/loser_mode.ml diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/loser_mode.mli b/src/lib_smart_rollup_node/loser_mode.mli similarity index 100% rename from src/proto_016_PtMumbai/lib_sc_rollup_node/loser_mode.mli rename to src/lib_smart_rollup_node/loser_mode.mli diff --git a/src/proto_016_PtMumbai/bin_sc_rollup_node/dune b/src/proto_016_PtMumbai/bin_sc_rollup_node/dune index 2e989520ffd045583b45a19b956fb8e38b6016c2..486f1b53bf69aec6c1b8a534ba60f98d7ebabfa5 100644 --- a/src/proto_016_PtMumbai/bin_sc_rollup_node/dune +++ b/src/proto_016_PtMumbai/bin_sc_rollup_node/dune @@ -15,6 +15,7 @@ tezos-client-base-unix tezos-client-commands tezos-client-016-PtMumbai + octez-smart-rollup-node octez_smart_rollup_node_PtMumbai) (link_flags (:standard) @@ -31,4 +32,5 @@ -open Tezos_client_base_unix -open Tezos_client_commands -open Tezos_client_016_PtMumbai + -open Octez_smart_rollup_node -open Octez_smart_rollup_node_PtMumbai)) 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 0a66833789c15b68eb12d7b8fe951d18dc242ded..09a5bf49d718ec12fb2747c3fc7ecbde396a9564 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 @@ -279,21 +279,32 @@ let make_operators sc_rollup_node_operators = in make_purpose_map purposed_operators ~default:default_operator +let convert_address sc_rollup_address = + sc_rollup_address + |> Data_encoding.Binary.to_bytes_exn + Protocol.Alpha_context.Sc_rollup.Address.encoding + |> Data_encoding.Binary.of_bytes_exn + Tezos_crypto.Hashed.Smart_rollup_address.encoding + let configuration_from_args ~rpc_addr ~rpc_port ~metrics_addr ~loser_mode ~reconnection_delay ~dal_node_endpoint ~injector_attempts ~injector_retention_period ~injection_ttl ~mode ~sc_rollup_address ~sc_rollup_node_operators ~log_kernel_debug = let open Configuration in let sc_rollup_node_operators = make_operators sc_rollup_node_operators in + let sc_rollup_address = convert_address sc_rollup_address in let config = { sc_rollup_address; + boot_sector_file = None; sc_rollup_node_operators; rpc_addr = Option.value ~default:default_rpc_addr rpc_addr; rpc_port = Option.value ~default:default_rpc_port rpc_port; reconnection_delay = Option.value ~default:default_reconnection_delay reconnection_delay; dal_node_endpoint; + dac_observer_endpoint = None; + dac_timeout = None; metrics_addr; fee_parameters = Operator_purpose_map.empty; mode; @@ -329,6 +340,7 @@ let patch_configuration_from_args configuration ~rpc_addr ~rpc_port new_sc_rollup_node_operators configuration.sc_rollup_node_operators in + let sc_rollup_address = Option.map convert_address sc_rollup_address in let configuration = Configuration. { diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/batcher.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/batcher.ml index d45abd021e60d7f6535037faf5c57409626ed0dc..273b3a9a0725b5a835425aed7884d16421ec314a 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/batcher.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/batcher.ml @@ -71,10 +71,19 @@ module Make (Simulation : Simulation.S) : S = struct type status = Pending_batch | Batched of Injector.Inj_operation.hash + (* Same as {!Configuration.batcher} with max_batch_size non optional. *) + type conf = { + simulate : bool; + min_batch_elements : int; + min_batch_size : int; + max_batch_elements : int; + max_batch_size : int; + } + type state = { node_ctxt : Node_context.ro; signer : Tezos_crypto.Signature.public_key_hash; - conf : Configuration.batcher; + conf : conf; messages : Message_queue.t; batched : Batched_messages.t; mutable simulation_ctxt : Simulation.t option; @@ -249,8 +258,20 @@ module Make (Simulation : Simulation.S) : S = struct (* Forget failing messages *) List.iter (Message_queue.remove state.messages) failing - let init_batcher_state node_ctxt ~signer conf = + let init_batcher_state node_ctxt ~signer (conf : Configuration.batcher) = let open Lwt_syntax in + let conf = + { + simulate = conf.simulate; + min_batch_elements = conf.min_batch_elements; + min_batch_size = conf.min_batch_size; + max_batch_elements = conf.max_batch_elements; + max_batch_size = + Option.value + conf.max_batch_size + ~default:Node_context.protocol_max_batch_size; + } + in return { node_ctxt; diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/configuration.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/configuration.ml deleted file mode 100644 index 2668952cdd0d503eff9019eab0aa0921e83125df..0000000000000000000000000000000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/configuration.ml +++ /dev/null @@ -1,672 +0,0 @@ -(*****************************************************************************) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -open Protocol.Alpha_context - -type mode = Observer | Accuser | Batcher | Maintenance | Operator | Custom - -type purpose = Publish | Add_messages | Cement | Timeout | Refute - -let purposes = [Publish; Add_messages; Cement; Timeout; Refute] - -module Operator_purpose_map = Map.Make (struct - type t = purpose - - let compare = Stdlib.compare -end) - -type operators = Tezos_crypto.Signature.Public_key_hash.t Operator_purpose_map.t - -type fee_parameters = Injection.fee_parameter Operator_purpose_map.t - -type batcher = { - simulate : bool; - min_batch_elements : int; - min_batch_size : int; - max_batch_elements : int; - max_batch_size : int; -} - -type injector = {retention_period : int; attempts : int; injection_ttl : int} - -type t = { - sc_rollup_address : Sc_rollup.t; - sc_rollup_node_operators : operators; - rpc_addr : string; - rpc_port : int; - metrics_addr : string option; - reconnection_delay : float; - fee_parameters : fee_parameters; - mode : mode; - loser_mode : Loser_mode.t; - dal_node_endpoint : Uri.t option; - batcher : batcher; - injector : injector; - l2_blocks_cache_size : int; - log_kernel_debug : bool; -} - -let default_data_dir = - Filename.concat (Sys.getenv "HOME") ".tezos-smart-rollup-node" - -let storage_dir = "storage" - -let context_dir = "context" - -let default_storage_dir data_dir = Filename.concat data_dir storage_dir - -let default_context_dir data_dir = Filename.concat data_dir context_dir - -let config_filename ~data_dir = Filename.concat data_dir "config.json" - -let default_rpc_addr = "127.0.0.1" - -let default_rpc_port = 8932 - -let default_metrics_port = 9933 - -let default_reconnection_delay = 2.0 (* seconds *) - -let tez t = Tez.of_mutez_exn Int64.(mul (of_int t) 1_000_000L) - -let default_minimal_fees = Mempool.default_minimal_fees - -let default_minimal_nanotez_per_gas_unit = - Mempool.default_minimal_nanotez_per_gas_unit - -let default_minimal_nanotez_per_byte = Mempool.default_minimal_nanotez_per_byte - -let default_force_low_fee = false - -let default_fee_cap = tez 1 - -let default_burn_cap = Tez.zero - -(* The below default fee and burn limits are computed by taking into account - the worst fee found in the tests for the rollup node. - - We take as base the cost of commitment cementation, which is 719 mutez in fees: - - Commitment publishing is 1.37 times more expensive. - - Message submission is 0.7 times more expensive, so cheaper but it depends on - the size of the message. - - For refutation games: - - Open is 1.55 times more expensive. - - Dissection move is 2.31 times more expensive. - - Proof move is 1.47 times more expensive but depends on the size of the proof. - - Timeout move is 1.34 times more expensive. - - We set a fee limit of 1 tz for cementation (instead of 719 mutez) which - should be plenty enough even if the gas price or gas consumption - increases. We adjust the other limits in proportion. -*) -let default_fee = function - | Cement -> tez 1 - | Publish -> tez 2 - | Add_messages -> - (* We keep this limit even though it depends on the size of the message - because the rollup node pays the fees for messages submitted by the - **users**. *) - tez 1 - | Timeout -> tez 2 - | Refute -> - (* Should be 3 based on comment above but we want to make sure we inject - refutation moves even if the proof is large. The stake is high (we can - lose the 10k deposit or we can get the reward). *) - tez 5 - -let default_burn = function - | Publish -> - (* The first commitment can store data. *) - tez 1 - | Add_messages -> tez 0 - | Cement -> tez 0 - | Timeout -> tez 0 - | Refute -> - (* A refutation move can store data, e.g. opening a game. *) - tez 1 - -let default_fee_parameter ?purpose () = - let fee_cap, burn_cap = - match purpose with - | None -> (default_fee_cap, default_burn_cap) - | Some purpose -> (default_fee purpose, default_burn purpose) - in - { - Injection.minimal_fees = default_minimal_fees; - minimal_nanotez_per_byte = default_minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit; - force_low_fee = default_force_low_fee; - fee_cap; - burn_cap; - } - -let default_fee_parameters = - List.fold_left - (fun acc purpose -> - Operator_purpose_map.add purpose (default_fee_parameter ~purpose ()) acc) - Operator_purpose_map.empty - purposes - -let default_batcher_simulate = true - -let default_batcher_min_batch_elements = 10 - -let default_batcher_min_batch_size = 10 - -let default_batcher_max_batch_elements = max_int - -let protocol_max_batch_size = - let empty_message_op : _ Operation.t = - let open Protocol in - let open Alpha_context in - let open Operation in - { - shell = {branch = Block_hash.zero}; - protocol_data = - { - signature = Some Tezos_crypto.Signature.zero; - contents = - Single - (Manager_operation - { - source = Tezos_crypto.Signature.Public_key_hash.zero; - fee = Tez.of_mutez_exn Int64.max_int; - counter = Manager_counter.Internal_for_tests.of_int max_int; - gas_limit = - Gas.Arith.integral_of_int_exn ((max_int - 1) / 1000); - storage_limit = Z.of_int max_int; - operation = Sc_rollup_add_messages {messages = [""]}; - }); - }; - } - in - Protocol.Constants_repr.max_operation_data_length - - Data_encoding.Binary.length - Operation.encoding - (Operation.pack empty_message_op) - -let default_batcher_max_batch_size = protocol_max_batch_size - -let default_batcher = - { - simulate = default_batcher_simulate; - min_batch_elements = default_batcher_min_batch_elements; - min_batch_size = default_batcher_min_batch_size; - max_batch_elements = default_batcher_max_batch_elements; - max_batch_size = default_batcher_max_batch_size; - } - -let default_injector = - {retention_period = 2048; attempts = 100; injection_ttl = 120} - -let max_injector_retention_period = - 5 * 8192 (* Preserved cycles (5) for mainnet *) - -let default_l2_blocks_cache_size = 64 - -let string_of_purpose = function - | Publish -> "publish" - | Add_messages -> "add_messages" - | Cement -> "cement" - | Timeout -> "timeout" - | Refute -> "refute" - -let purpose_of_string = function - | "publish" -> Some Publish - | "add_messages" -> Some Add_messages - | "cement" -> Some Cement - | "timeout" -> Some Timeout - | "refute" -> Some Refute - | _ -> None - -let purpose_of_string_exn s = - match purpose_of_string s with - | Some p -> p - | None -> invalid_arg ("purpose_of_string " ^ s) - -let add_fallbacks map fallbacks = - List.fold_left - (fun map (missing_purpose, fallback_purpose) -> - if Operator_purpose_map.mem missing_purpose map then - (* No missing purpose, don't fallback *) - map - else - match Operator_purpose_map.find fallback_purpose map with - | None -> - (* Nothing to fallback on *) - map - | Some operator -> Operator_purpose_map.add missing_purpose operator map) - map - fallbacks - -let make_purpose_map ~default bindings = - let map = Operator_purpose_map.of_seq @@ List.to_seq bindings in - let map = add_fallbacks map [(Timeout, Refute)] in - match default with - | None -> map - | Some default -> - List.fold_left - (fun map purpose -> - if Operator_purpose_map.mem purpose map then map - else Operator_purpose_map.add purpose default map) - map - purposes - -let operator_purpose_map_encoding encoding = - let open Data_encoding in - let schema = - let open Json_schema in - let v_schema p = Data_encoding.Json.schema (encoding p) in - let v_schema_r p = root (v_schema p) in - let kind = - Object - { - properties = - List.map - (fun purpose -> - (string_of_purpose purpose, v_schema_r purpose, false, None)) - purposes; - pattern_properties = []; - additional_properties = None; - min_properties = 0; - max_properties = None; - schema_dependencies = []; - property_dependencies = []; - } - in - update (element kind) (v_schema Publish (* Dummy for definitions *)) - in - conv - ~schema - (fun map -> - let fields = - Operator_purpose_map.bindings map - |> List.map (fun (p, v) -> - (string_of_purpose p, Data_encoding.Json.construct (encoding p) v)) - in - `O fields) - (function - | `O fields -> - List.map - (fun (p, v) -> - let purpose = purpose_of_string_exn p in - (purpose, Data_encoding.Json.destruct (encoding purpose) v)) - fields - |> List.to_seq |> Operator_purpose_map.of_seq - | _ -> assert false) - Data_encoding.Json.encoding - -let operators_encoding = - operator_purpose_map_encoding (fun _ -> - Tezos_crypto.Signature.Public_key_hash.encoding) - -let fee_parameter_encoding purpose = - let open Data_encoding in - conv - (fun { - Injection.minimal_fees; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap; - burn_cap; - } -> - ( minimal_fees, - minimal_nanotez_per_byte, - minimal_nanotez_per_gas_unit, - force_low_fee, - fee_cap, - burn_cap )) - (fun ( minimal_fees, - minimal_nanotez_per_byte, - minimal_nanotez_per_gas_unit, - force_low_fee, - fee_cap, - burn_cap ) -> - { - minimal_fees; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap; - burn_cap; - }) - (obj6 - (dft - "minimal-fees" - ~description:"Exclude operations with lower fees" - Tez.encoding - default_minimal_fees) - (dft - "minimal-nanotez-per-byte" - ~description:"Exclude operations with lower fees per byte" - Plugin.Mempool.nanotez_enc - default_minimal_nanotez_per_byte) - (dft - "minimal-nanotez-per-gas-unit" - ~description:"Exclude operations with lower gas fees" - Plugin.Mempool.nanotez_enc - default_minimal_nanotez_per_gas_unit) - (dft - "force-low-fee" - ~description: - "Don't check that the fee is lower than the estimated default" - bool - default_force_low_fee) - (dft - "fee-cap" - ~description:"The fee cap" - Tez.encoding - (default_fee purpose)) - (dft - "burn-cap" - ~description:"The burn cap" - Tez.encoding - (default_burn purpose))) - -let fee_parameters_encoding = - operator_purpose_map_encoding fee_parameter_encoding - -let modes = [Observer; Batcher; Maintenance; Operator; Custom] - -let string_of_mode = function - | Observer -> "observer" - | Accuser -> "accuser" - | Batcher -> "batcher" - | Maintenance -> "maintenance" - | Operator -> "operator" - | Custom -> "custom" - -let mode_of_string = function - | "observer" -> Ok Observer - | "accuser" -> Ok Accuser - | "batcher" -> Ok Batcher - | "maintenance" -> Ok Maintenance - | "operator" -> Ok Operator - | "custom" -> Ok Custom - | _ -> Error [Exn (Failure "Invalid mode")] - -let description_of_mode = function - | Observer -> "Only follows the chain, reconstructs and interprets inboxes" - | Accuser -> - "Only publishes commitments for conflicts and play refutation games" - | Batcher -> "Accepts transactions in its queue and batches them on the L1" - | Maintenance -> - "Follows the chain and publishes commitments, cement and refute" - | Operator -> "Equivalent to maintenance + batcher" - | Custom -> - "In this mode, only operations that have a corresponding operator/signer \ - are injected" - -let mode_encoding = - Data_encoding.string_enum - [ - ("observer", Observer); - ("accuser", Accuser); - ("batcher", Batcher); - ("maintenance", Maintenance); - ("operator", Operator); - ("custom", Custom); - ] - -let batcher_encoding = - let open Data_encoding in - conv_with_guard - (fun { - simulate; - min_batch_elements; - min_batch_size; - max_batch_elements; - max_batch_size; - } -> - ( simulate, - min_batch_elements, - min_batch_size, - max_batch_elements, - max_batch_size )) - (fun ( simulate, - min_batch_elements, - min_batch_size, - max_batch_elements, - max_batch_size ) -> - if max_batch_size > protocol_max_batch_size then - Error - (Format.sprintf - "max_batch_size must be smaller than %d" - protocol_max_batch_size) - else if min_batch_size <= 0 then Error "min_batch_size must be positive" - else if max_batch_size < min_batch_size then - Error "max_batch_size must be greater than min_batch_size" - else if min_batch_elements <= 0 then - Error "min_batch_elements must be positive" - else if max_batch_elements < min_batch_elements then - Error "max_batch_elements must be greater than min_batch_elements" - else - Ok - { - simulate; - min_batch_elements; - min_batch_size; - max_batch_elements; - max_batch_size; - }) - @@ obj5 - (dft "simulate" bool default_batcher_simulate) - (dft "min_batch_elements" int31 default_batcher_min_batch_elements) - (dft "min_batch_size" int31 default_batcher_min_batch_size) - (dft "max_batch_elements" int31 default_batcher_max_batch_elements) - (dft "max_batch_size" int31 default_batcher_max_batch_size) - -let injector_encoding : injector Data_encoding.t = - let open Data_encoding in - conv - (fun {retention_period; attempts; injection_ttl} -> - (retention_period, attempts, injection_ttl)) - (fun (retention_period, attempts, injection_ttl) -> - if retention_period > max_injector_retention_period then - Format.ksprintf - Stdlib.failwith - "injector.retention_period should be smaller than %d" - max_injector_retention_period ; - if injection_ttl < 1 then - Stdlib.failwith "injector.injection_ttl should be at least 1" ; - {retention_period; attempts; injection_ttl}) - @@ obj3 - (dft "retention_period" uint16 default_injector.retention_period) - (dft "attempts" uint16 default_injector.attempts) - (dft "injection_ttl" uint16 default_injector.injection_ttl) - -let encoding : t Data_encoding.t = - let open Data_encoding in - conv - (fun { - sc_rollup_address; - sc_rollup_node_operators; - rpc_addr; - rpc_port; - metrics_addr; - reconnection_delay; - fee_parameters; - mode; - loser_mode; - dal_node_endpoint; - batcher; - injector; - l2_blocks_cache_size; - log_kernel_debug; - } -> - ( ( sc_rollup_address, - sc_rollup_node_operators, - rpc_addr, - rpc_port, - metrics_addr, - reconnection_delay, - fee_parameters, - mode, - loser_mode ), - ( dal_node_endpoint, - batcher, - injector, - l2_blocks_cache_size, - log_kernel_debug ) )) - (fun ( ( sc_rollup_address, - sc_rollup_node_operators, - rpc_addr, - rpc_port, - metrics_addr, - reconnection_delay, - fee_parameters, - mode, - loser_mode ), - ( dal_node_endpoint, - batcher, - injector, - l2_blocks_cache_size, - log_kernel_debug ) ) -> - { - sc_rollup_address; - sc_rollup_node_operators; - rpc_addr; - rpc_port; - metrics_addr; - reconnection_delay; - fee_parameters; - mode; - loser_mode; - dal_node_endpoint; - batcher; - injector; - l2_blocks_cache_size; - log_kernel_debug; - }) - (merge_objs - (obj9 - (req - "smart-rollup-address" - ~description:"Smart rollup address" - Protocol.Alpha_context.Sc_rollup.Address.encoding) - (req - "smart-rollup-node-operator" - ~description: - "Operators that sign operations of the smart rollup, by purpose" - operators_encoding) - (dft "rpc-addr" ~description:"RPC address" string default_rpc_addr) - (dft "rpc-port" ~description:"RPC port" uint16 default_rpc_port) - (opt "metrics-addr" ~description:"Metrics address" string) - (dft - "reconnection_delay" - ~description: - "The reconnection (to the tezos node) delay in seconds" - float - default_reconnection_delay) - (dft - "fee-parameters" - ~description: - "The fee parameters for each purpose used when injecting \ - operations in L1" - fee_parameters_encoding - default_fee_parameters) - (req - ~description:"The mode for this rollup node" - "mode" - mode_encoding) - (dft - "loser-mode" - ~description: - "If enabled, the rollup node will issue wrong commitments (for \ - test only!)" - Loser_mode.encoding - Loser_mode.no_failures)) - (obj5 - (opt "DAL node endpoint" Tezos_rpc.Encoding.uri_encoding) - (dft "batcher" batcher_encoding default_batcher) - (dft "injector" injector_encoding default_injector) - (dft "l2_blocks_cache_size" int31 default_l2_blocks_cache_size) - (dft "log-kernel-debug" Data_encoding.bool false))) - -let check_mode config = - let open Result_syntax in - let check_purposes purposes = - let missing_operators = - List.filter - (fun p -> - not (Operator_purpose_map.mem p config.sc_rollup_node_operators)) - purposes - in - if missing_operators <> [] then - let mode = string_of_mode config.mode in - let missing_operators = List.map string_of_purpose missing_operators in - tzfail - (Sc_rollup_node_errors.Missing_mode_operators {mode; missing_operators}) - else return_unit - in - let narrow_purposes purposes = - let+ () = check_purposes purposes in - let sc_rollup_node_operators = - Operator_purpose_map.filter - (fun op_purpose _ -> List.mem ~equal:Stdlib.( = ) op_purpose purposes) - config.sc_rollup_node_operators - in - {config with sc_rollup_node_operators} - in - match config.mode with - | Observer -> narrow_purposes [] - | Batcher -> narrow_purposes [Add_messages] - | Accuser -> narrow_purposes [Publish; Refute] - | Maintenance -> narrow_purposes [Publish; Cement; Refute] - | Operator -> narrow_purposes [Publish; Cement; Add_messages; Refute] - | Custom -> return config - -let loser_warning_message config = - if config.loser_mode <> Loser_mode.no_failures then - Format.printf - {| -************ WARNING ************* -This rollup node is in loser mode. -This should be used for test only! -************ WARNING ************* -|} - -let save ~force ~data_dir config = - loser_warning_message config ; - let open Lwt_result_syntax in - let json = Data_encoding.Json.construct encoding config in - let config_file = config_filename ~data_dir in - let*! exists = Lwt_unix.file_exists config_file in - if exists && not force then - failwith - "Configuration file %S already exists. Use --force to overwrite." - config_file - else - let*! () = Lwt_utils_unix.create_dir data_dir in - Lwt_utils_unix.Json.write_file config_file json - -let load ~data_dir = - let open Lwt_result_syntax in - let+ json = Lwt_utils_unix.Json.read_file (config_filename ~data_dir) in - let config = Data_encoding.Json.destruct encoding json in - loser_warning_message config ; - config diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/configuration.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/configuration.mli deleted file mode 100644 index 2b51ecc8457c18d8bc1de898188b87c567be9201..0000000000000000000000000000000000000000 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/configuration.mli +++ /dev/null @@ -1,188 +0,0 @@ -(*****************************************************************************) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -(** Mode for the rollup node *) -type mode = - | Observer (** Only follows the chain and reconstructs inboxes *) - | Accuser - (** Only publishes commitments for conflicts and play refutation games *) - | Batcher (** Accept transactions in its queue and batches them on the L1 *) - | Maintenance (** Follows the chain and publishes commitments *) - | Operator (** Equivalent to maintenance + batcher *) - | Custom - (** This mode allows to tweak which operations are injected by selecting - the signers *) - -(** Purposes for operators, indicating the kind of operations that they sign. *) -type purpose = Publish | Add_messages | Cement | Timeout | Refute - -module Operator_purpose_map : Map.S with type key = purpose - -type operators = Tezos_crypto.Signature.Public_key_hash.t Operator_purpose_map.t - -type fee_parameters = Injection.fee_parameter Operator_purpose_map.t - -(** Configuration for the batcher. - - Invariants: - - 0 < [min_batch_size] <= [max_batch_size] <= [protocol_max_batch_size] - - 0 < [min_batch_elements] <= [max_batch_elements] -*) -type batcher = { - simulate : bool; - (** If [true], the batcher will simulate the messages it receives, in an - incremental context, before queuing them. *) - min_batch_elements : int; - (** The minimum number elements in a batch for it to be produced when the - batcher receives new messages. *) - min_batch_size : int; - (** The minimum size in bytes of a batch for it to be produced when the - batcher receives new messages. *) - max_batch_elements : int; - (** The maximum number of elements that we can put in a batch. *) - max_batch_size : int; (** The maximum size in bytes of a batch. *) -} - -type injector = { - retention_period : int; - (** The number of blocks during which the injector will keep track of an - operation (in addition to the confirmation period). *) - attempts : int; - (** The number of attempts that will be made to inject an operation. *) - injection_ttl : int; - (** The number of blocks after which an operation that is injected but - never included is retried. *) -} - -type t = { - sc_rollup_address : Protocol.Alpha_context.Sc_rollup.t; - sc_rollup_node_operators : operators; - rpc_addr : string; - rpc_port : int; - metrics_addr : string option; - reconnection_delay : float; - fee_parameters : fee_parameters; - mode : mode; - loser_mode : Loser_mode.t; - (*DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/3718 - Decide whether we want to handle connections to multiple - Dal nodes for different slot indexes. - *) - dal_node_endpoint : Uri.t option; - batcher : batcher; - injector : injector; - l2_blocks_cache_size : int; - log_kernel_debug : bool; -} - -(** [make_purpose_map ~default purposes] constructs a purpose map from a list of - bindings [purposes], with a potential [default] value. *) -val make_purpose_map : - default:'a option -> (purpose * 'a) trace -> 'a Operator_purpose_map.t - -(** [purpose_of_string s] parses a purpose from the given string [s]. *) -val purpose_of_string : string -> purpose option - -(** [string_of_purpose p] returns a string representation of purpose [p]. *) -val string_of_purpose : purpose -> string - -(** List of possible purposes for operator specialization. *) -val purposes : purpose list - -(** [default_data_dir] is the default value for [data_dir]. *) -val default_data_dir : string - -(** [default_storage_dir] returns the default value of the storage dir - given a [data_dir]. *) -val default_storage_dir : string -> string - -(** [default_context_dir] returns the default value of the directory - for persisting the context given a [data_dir]. *) -val default_context_dir : string -> string - -(** [default_rpc_addr] is the default value for [rpc_addr]. *) -val default_rpc_addr : string - -(** [default_rpc_port] is the default value for [rpc_port]. *) -val default_rpc_port : int - -(** [default_metrics_port] is the default port for the metrics server. *) -val default_metrics_port : int - -(** [default_reconnection_delay] is the default value for [reconnection_delay]. *) -val default_reconnection_delay : float - -(** [default_fee_parameter ?purpose ()] is the default fee parameter to inject - operation on L1. If [purpose] is provided, it returns the default fee - parameter for the specific purpose. *) -val default_fee_parameter : ?purpose:purpose -> unit -> Injection.fee_parameter - -(** [default_fee_parameters] is the default fee parameters configuration build - with {!default_fee_parameter} for all purposes. *) -val default_fee_parameters : fee_parameters - -(** [default_batcher] is the default configuration parameters for the batcher. *) -val default_batcher : batcher - -(** [default_injector] is the default configuration parameters for the - injector. *) -val default_injector : injector - -(** [default_l2_blocks_cache_size] is the default number of L2 blocks that are - cached by the rollup node *) -val default_l2_blocks_cache_size : int - -(** [max_injector_retention_period] is the maximum allowed value for - [injector_retention_period]. *) -val max_injector_retention_period : int - -(** This is the list of available modes. *) -val modes : mode list - -(** [string_of_mode mode] returns a string representation of the mode [mode]. *) -val string_of_mode : mode -> string - -(** [mode_of_string s] returns the mode represented by string [s] if it exists. *) -val mode_of_string : string -> mode tzresult - -(** [description_of_mode m] returns a textual description of the mode [m]. *) -val description_of_mode : mode -> string - -(** [config_filename data_dir] returns - the configration filename from the [data_dir] *) -val config_filename : data_dir:string -> string - -(** [check_mode config] ensures the operators correspond to the chosen mode and - removes the extra ones. *) -val check_mode : t -> t tzresult - -(** [save ~force ~data_dir configuration] writes the [configuration] file in - [data_dir]. If [force] is [true], existing configurations are - overwritten. *) -val save : force:bool -> data_dir:string -> t -> unit tzresult Lwt.t - -(** [load ~data_dir] loads a configuration stored in [data_dir]. *) -val load : data_dir:string -> t tzresult Lwt.t diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/dune b/src/proto_016_PtMumbai/lib_sc_rollup_node/dune index 5827d992e67884ea58321900b4ccd38e0b9f2c37..a49d5c1cfe1e47d019197155b73b8a5524e3a384 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/dune +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/dune @@ -36,6 +36,7 @@ aches aches-lwt octez-injector + octez-smart-rollup-node tezos-scoru-wasm tezos-scoru-wasm-fast tezos-crypto-dal @@ -62,4 +63,5 @@ -open Tezos_layer2_store -open Octez_crawler -open Octez_injector + -open Octez_smart_rollup_node -open Tezos_crypto_dal)) diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml index bc0d0cf333a861982d4f2e52e9e56c222505bbf5..c239e844e72bed6715efb7344785a470d06e79da 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/injector.ml @@ -79,24 +79,7 @@ module Parameters : | Refute _ -> Refute let fee_parameter node_ctxt operation = - let { - Injection.minimal_fees; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap; - burn_cap; - } = - Node_context.get_fee_parameter node_ctxt (operation_tag operation) - in - { - minimal_fees = {mutez = Tez.to_mutez minimal_fees}; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap = {mutez = Tez.to_mutez fee_cap}; - burn_cap = {mutez = Tez.to_mutez burn_cap}; - } + Node_context.get_fee_parameter node_ctxt (operation_tag operation) (* TODO: https://gitlab.com/tezos/tezos/-/issues/3459 Decide if some batches must have all the operations succeed. See diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml index f740ed4fe79cce8a42955124edce19369043fbfb..64f584b83961b28d622d29d5624b836c56b33dee 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.ml @@ -61,6 +61,17 @@ type rw = [`Read | `Write] t type ro = [`Read] t +let () = + if + Tezos_crypto.Hashed.Smart_rollup_address.size + <> Protocol.Alpha_context.Sc_rollup.Address.size + then + Format.ksprintf + Stdlib.failwith + "Protocol %s is not compatible with rollup addresses of size %d" + Protocol.name + Tezos_crypto.Hashed.Smart_rollup_address.size + let get_operator node_ctxt purpose = Configuration.Operator_purpose_map.find purpose node_ctxt.operators @@ -177,6 +188,99 @@ let make_kernel_logger ?log_kernel_debug_file data_dir = in Lwt_io.of_fd ~close:(fun () -> Lwt_unix.close fd) ~mode:Lwt_io.Output fd +let check_fee_parameters Configuration.{fee_parameters; _} = + let check_value purpose name compare to_string mempool_default value = + if compare mempool_default value > 0 then + error_with + "Bad configuration fee_parameter.%s for %s. It must be at least %s for \ + operations of the injector to be propagated." + name + (Configuration.string_of_purpose purpose) + (to_string mempool_default) + else Ok () + in + let check purpose + { + Injector_sigs.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee = _; + fee_cap = _; + burn_cap = _; + } = + let open Result_syntax in + let+ () = + check_value + purpose + "minimal_fees" + Int64.compare + Int64.to_string + (Tez.to_mutez Plugin.Mempool.default_minimal_fees) + minimal_fees.mutez + and+ () = + check_value + purpose + "minimal_nanotez_per_byte" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_byte + minimal_nanotez_per_byte + and+ () = + check_value + purpose + "minimal_nanotez_per_gas_unit" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_gas_unit + minimal_nanotez_per_gas_unit + in + () + in + Configuration.Operator_purpose_map.iter_e check fee_parameters + +let protocol_max_batch_size = + let empty_message_op : _ Operation.t = + let open Protocol in + let open Alpha_context in + let open Operation in + { + shell = {branch = Block_hash.zero}; + protocol_data = + { + signature = Some Signature.zero; + contents = + Single + (Manager_operation + { + source = Signature.Public_key_hash.zero; + fee = Tez.of_mutez_exn Int64.max_int; + counter = Manager_counter.Internal_for_tests.of_int max_int; + gas_limit = + Gas.Arith.integral_of_int_exn ((max_int - 1) / 1000); + storage_limit = Z.of_int max_int; + operation = Sc_rollup_add_messages {messages = [""]}; + }); + }; + } + in + Protocol.Constants_repr.max_operation_data_length + - Data_encoding.Binary.length + Operation.encoding + (Operation.pack empty_message_op) + +let check_batcher_config Configuration.{batcher = {max_batch_size; _}; _} = + match max_batch_size with + | Some m when m > protocol_max_batch_size -> + error_with + "batcher.max_batch_size must be smaller than %d" + protocol_max_batch_size + | _ -> Ok () + +let check_config config = + let open Result_syntax in + let+ () = check_fee_parameters config and+ () = check_batcher_config config in + () + let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file mode Configuration.( @@ -192,6 +296,12 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file _; } as configuration) = let open Lwt_result_syntax in + let*? () = check_config configuration in + let rollup_address = + (* Convert to protocol rollup address *) + Tezos_crypto.Hashed.Smart_rollup_address.to_bytes rollup_address + |> Protocol.Alpha_context.Sc_rollup.Address.of_bytes_exn + in let* lockfile = lock ~data_dir in let dal_cctxt = Option.map Dal_node_client.make_unix_cctxt dal_node_endpoint @@ -221,7 +331,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file and* genesis_info = RPC.Sc_rollup.genesis_info cctxt (cctxt#chain, cctxt#block) rollup_address in - let*! () = Event.rollup_exists ~addr:configuration.sc_rollup_address ~kind in + let*! () = Event.rollup_exists ~addr:rollup_address ~kind in let*! () = if dal_cctxt = None && protocol_constants.parametric.dal.feature_enable then Event.warn_dal_enabled_no_node () diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli index 53ab58a46c992da8d66535544469629d7d4951a2..411710c5b7c68c0face04e97b2636c62a2a4347a 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/node_context.mli @@ -111,7 +111,12 @@ val is_loser : _ t -> bool configured for this purpose, returns the default fee parameter for this purpose. *) -val get_fee_parameter : _ t -> Configuration.purpose -> Injection.fee_parameter +val get_fee_parameter : + _ t -> Configuration.purpose -> Injector_sigs.fee_parameter + +(** Maximum size of an L2 batch in bytes that can fit in an operation of the + protocol. *) +val protocol_max_batch_size : int (** [init cctxt ~data_dir mode configuration] initializes the rollup representation. The rollup origination level and kind are fetched via an RPC diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/sc_rollup_node_errors.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/sc_rollup_node_errors.ml index 344aa528c00db39c5832cbaa0074a9acae2a78c8..75f4fd02e92bcce2c9c4b6ffb75a0d5ccc25fca1 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/sc_rollup_node_errors.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/sc_rollup_node_errors.ml @@ -31,7 +31,6 @@ let register_error_kind ~id = register_error_kind ~id:(make_id id) type error += | Cannot_produce_proof of Sc_rollup.Game.t - | Missing_mode_operators of {mode : string; missing_operators : string list} | Bad_minimal_fees of string | Disagree_with_cemented of { inbox_level : Raw_level.t; @@ -144,29 +143,6 @@ let () = (function Cannot_produce_proof game -> Some game | _ -> None) (fun game -> Cannot_produce_proof game) ; - register_error_kind - ~id:"sc_rollup.node.missing_mode_operators" - ~title:"Missing operators for the chosen mode" - ~description:"Missing operators for the chosen mode." - ~pp:(fun ppf (mode, missing_operators) -> - Format.fprintf - ppf - "@[Missing operators %a for mode %s.@]" - (Format.pp_print_list - ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ") - Format.pp_print_string) - missing_operators - mode) - `Permanent - Data_encoding.( - obj2 (req "mode" string) (req "missing_operators" (list string))) - (function - | Missing_mode_operators {mode; missing_operators} -> - Some (mode, missing_operators) - | _ -> None) - (fun (mode, missing_operators) -> - Missing_mode_operators {mode; missing_operators}) ; - register_error_kind ~id:"sc_rollup.node.Wrong_initial_pvm_state" ~title:"Initial state produced by PVM is incorrect" diff --git a/src/proto_017_PtNairob/bin_sc_rollup_node/dune b/src/proto_017_PtNairob/bin_sc_rollup_node/dune index a16af5eb5bb5d8cd38279b1c38eb1102da794e4f..2c9fb67fd74aeab1680f9a4922bd1d35b8e0a79f 100644 --- a/src/proto_017_PtNairob/bin_sc_rollup_node/dune +++ b/src/proto_017_PtNairob/bin_sc_rollup_node/dune @@ -15,6 +15,7 @@ tezos-client-base-unix tezos-client-commands tezos-client-017-PtNairob + octez-smart-rollup-node octez_smart_rollup_node_PtNairob) (link_flags (:standard) @@ -31,4 +32,5 @@ -open Tezos_client_base_unix -open Tezos_client_commands -open Tezos_client_017_PtNairob + -open Octez_smart_rollup_node -open Octez_smart_rollup_node_PtNairob)) 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 b0b9d51270bdf51a1773b9e05e42db80ef67ac12..562693b0928bf8a8abac9a66b1e1f0396f96eac2 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 @@ -279,21 +279,32 @@ let make_operators sc_rollup_node_operators = in make_purpose_map purposed_operators ~default:default_operator +let convert_address sc_rollup_address = + sc_rollup_address + |> Data_encoding.Binary.to_bytes_exn + Protocol.Alpha_context.Sc_rollup.Address.encoding + |> Data_encoding.Binary.of_bytes_exn + Tezos_crypto.Hashed.Smart_rollup_address.encoding + let configuration_from_args ~rpc_addr ~rpc_port ~metrics_addr ~loser_mode ~reconnection_delay ~dal_node_endpoint ~injector_retention_period ~injector_attempts ~injection_ttl ~mode ~sc_rollup_address ~sc_rollup_node_operators ~log_kernel_debug = let open Configuration in let sc_rollup_node_operators = make_operators sc_rollup_node_operators in + let sc_rollup_address = convert_address sc_rollup_address in let config = { sc_rollup_address; + boot_sector_file = None; sc_rollup_node_operators; rpc_addr = Option.value ~default:default_rpc_addr rpc_addr; rpc_port = Option.value ~default:default_rpc_port rpc_port; reconnection_delay = Option.value ~default:default_reconnection_delay reconnection_delay; dal_node_endpoint; + dac_observer_endpoint = None; + dac_timeout = None; metrics_addr; fee_parameters = Operator_purpose_map.empty; mode; @@ -329,6 +340,7 @@ let patch_configuration_from_args configuration ~rpc_addr ~rpc_port new_sc_rollup_node_operators configuration.sc_rollup_node_operators in + let sc_rollup_address = Option.map convert_address sc_rollup_address in let configuration = Configuration. { diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/batcher.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/batcher.ml index f2090acd06976860d79c7b7cca7279a2017fb4be..d317880cb45d843a14cba0862d77eb39dfcd8257 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/batcher.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/batcher.ml @@ -71,10 +71,19 @@ module Make (Simulation : Simulation.S) : S = struct type status = Pending_batch | Batched of Injector.Inj_operation.hash + (* Same as {!Configuration.batcher} with max_batch_size non optional. *) + type conf = { + simulate : bool; + min_batch_elements : int; + min_batch_size : int; + max_batch_elements : int; + max_batch_size : int; + } + type state = { node_ctxt : Node_context.ro; signer : Signature.public_key_hash; - conf : Configuration.batcher; + conf : conf; messages : Message_queue.t; batched : Batched_messages.t; mutable simulation_ctxt : Simulation.t option; @@ -249,8 +258,20 @@ module Make (Simulation : Simulation.S) : S = struct (* Forget failing messages *) List.iter (Message_queue.remove state.messages) failing - let init_batcher_state node_ctxt ~signer conf = + let init_batcher_state node_ctxt ~signer (conf : Configuration.batcher) = let open Lwt_syntax in + let conf = + { + simulate = conf.simulate; + min_batch_elements = conf.min_batch_elements; + min_batch_size = conf.min_batch_size; + max_batch_elements = conf.max_batch_elements; + max_batch_size = + Option.value + conf.max_batch_size + ~default:Node_context.protocol_max_batch_size; + } + in return { node_ctxt; diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/configuration.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/configuration.ml deleted file mode 100644 index acb074643f3c26337a9a52c2334139dce87161f6..0000000000000000000000000000000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/configuration.ml +++ /dev/null @@ -1,673 +0,0 @@ -(*****************************************************************************) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -open Protocol.Alpha_context - -type mode = Observer | Accuser | Batcher | Maintenance | Operator | Custom - -type purpose = Publish | Add_messages | Cement | Timeout | Refute - -let purposes = [Publish; Add_messages; Cement; Timeout; Refute] - -module Operator_purpose_map = Map.Make (struct - type t = purpose - - let compare = Stdlib.compare -end) - -type operators = Signature.Public_key_hash.t Operator_purpose_map.t - -type fee_parameters = Injection.fee_parameter Operator_purpose_map.t - -type batcher = { - simulate : bool; - min_batch_elements : int; - min_batch_size : int; - max_batch_elements : int; - max_batch_size : int; -} - -type injector = {retention_period : int; attempts : int; injection_ttl : int} - -type t = { - sc_rollup_address : Sc_rollup.t; - sc_rollup_node_operators : operators; - rpc_addr : string; - rpc_port : int; - metrics_addr : string option; - reconnection_delay : float; - fee_parameters : fee_parameters; - mode : mode; - loser_mode : Loser_mode.t; - dal_node_endpoint : Uri.t option; - batcher : batcher; - injector : injector; - l2_blocks_cache_size : int; - log_kernel_debug : bool; -} - -let default_data_dir = - Filename.concat (Sys.getenv "HOME") ".tezos-smart-rollup-node" - -let storage_dir = "storage" - -let context_dir = "context" - -let default_storage_dir data_dir = Filename.concat data_dir storage_dir - -let default_context_dir data_dir = Filename.concat data_dir context_dir - -let config_filename ~data_dir = Filename.concat data_dir "config.json" - -let default_rpc_addr = "127.0.0.1" - -let default_rpc_port = 8932 - -let default_metrics_port = 9933 - -let default_reconnection_delay = 2.0 (* seconds *) - -let tez t = Tez.of_mutez_exn Int64.(mul (of_int t) 1_000_000L) - -let default_minimal_fees = Mempool.default_minimal_fees - -let default_minimal_nanotez_per_gas_unit = - Mempool.default_minimal_nanotez_per_gas_unit - -let default_minimal_nanotez_per_byte = Mempool.default_minimal_nanotez_per_byte - -let default_force_low_fee = false - -let default_fee_cap = tez 1 - -let default_burn_cap = Tez.zero - -(* The below default fee and burn limits are computed by taking into account - the worst fee found in the tests for the rollup node. - - We take as base the cost of commitment cementation, which is 719 mutez in fees: - - Commitment publishing is 1.37 times more expensive. - - Message submission is 0.7 times more expensive, so cheaper but it depends on - the size of the message. - - For refutation games: - - Open is 1.55 times more expensive. - - Dissection move is 2.31 times more expensive. - - Proof move is 1.47 times more expensive but depends on the size of the proof. - - Timeout move is 1.34 times more expensive. - - We set a fee limit of 1 tz for cementation (instead of 719 mutez) which - should be plenty enough even if the gas price or gas consumption - increases. We adjust the other limits in proportion. -*) -let default_fee = function - | Cement -> tez 1 - | Publish -> tez 2 - | Add_messages -> - (* We keep this limit even though it depends on the size of the message - because the rollup node pays the fees for messages submitted by the - **users**. *) - tez 1 - | Timeout -> tez 2 - | Refute -> - (* Should be 3 based on comment above but we want to make sure we inject - refutation moves even if the proof is large. The stake is high (we can - lose the 10k deposit or we can get the reward). *) - tez 5 - -let default_burn = function - | Publish -> - (* The first commitment can store data. *) - tez 1 - | Add_messages -> tez 0 - | Cement -> tez 0 - | Timeout -> tez 0 - | Refute -> - (* A refutation move can store data, e.g. opening a game. *) - tez 1 - -let default_fee_parameter ?purpose () = - let fee_cap, burn_cap = - match purpose with - | None -> (default_fee_cap, default_burn_cap) - | Some purpose -> (default_fee purpose, default_burn purpose) - in - { - Injection.minimal_fees = default_minimal_fees; - minimal_nanotez_per_byte = default_minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit = default_minimal_nanotez_per_gas_unit; - force_low_fee = default_force_low_fee; - fee_cap; - burn_cap; - } - -let default_fee_parameters = - List.fold_left - (fun acc purpose -> - Operator_purpose_map.add purpose (default_fee_parameter ~purpose ()) acc) - Operator_purpose_map.empty - purposes - -let default_batcher_simulate = true - -let default_batcher_min_batch_elements = 10 - -let default_batcher_min_batch_size = 10 - -let default_batcher_max_batch_elements = max_int - -let protocol_max_batch_size = - let empty_message_op : _ Operation.t = - let open Protocol in - let open Alpha_context in - let open Operation in - { - shell = {branch = Block_hash.zero}; - protocol_data = - { - signature = Some Signature.zero; - contents = - Single - (Manager_operation - { - source = Signature.Public_key_hash.zero; - fee = Tez.of_mutez_exn Int64.max_int; - counter = Manager_counter.Internal_for_tests.of_int max_int; - gas_limit = - Gas.Arith.integral_of_int_exn ((max_int - 1) / 1000); - storage_limit = Z.of_int max_int; - operation = Sc_rollup_add_messages {messages = [""]}; - }); - }; - } - in - Protocol.Constants_repr.max_operation_data_length - - Data_encoding.Binary.length - Operation.encoding - (Operation.pack empty_message_op) - -let default_batcher_max_batch_size = protocol_max_batch_size - -let default_batcher = - { - simulate = default_batcher_simulate; - min_batch_elements = default_batcher_min_batch_elements; - min_batch_size = default_batcher_min_batch_size; - max_batch_elements = default_batcher_max_batch_elements; - max_batch_size = default_batcher_max_batch_size; - } - -let default_injector = - {retention_period = 2048; attempts = 100; injection_ttl = 120} - -let max_injector_retention_period = - 5 * 8192 (* Preserved cycles (5) for mainnet *) - -let default_l2_blocks_cache_size = 64 - -let string_of_purpose = function - | Publish -> "publish" - | Add_messages -> "add_messages" - | Cement -> "cement" - | Timeout -> "timeout" - | Refute -> "refute" - -let purpose_of_string = function - | "publish" -> Some Publish - | "add_messages" -> Some Add_messages - | "cement" -> Some Cement - | "timeout" -> Some Timeout - | "refute" -> Some Refute - | _ -> None - -let purpose_of_string_exn s = - match purpose_of_string s with - | Some p -> p - | None -> invalid_arg ("purpose_of_string " ^ s) - -let add_fallbacks map fallbacks = - List.fold_left - (fun map (missing_purpose, fallback_purpose) -> - if Operator_purpose_map.mem missing_purpose map then - (* No missing purpose, don't fallback *) - map - else - match Operator_purpose_map.find fallback_purpose map with - | None -> - (* Nothing to fallback on *) - map - | Some operator -> Operator_purpose_map.add missing_purpose operator map) - map - fallbacks - -let make_purpose_map ~default bindings = - let map = Operator_purpose_map.of_seq @@ List.to_seq bindings in - let map = add_fallbacks map [(Timeout, Refute)] in - match default with - | None -> map - | Some default -> - List.fold_left - (fun map purpose -> - if Operator_purpose_map.mem purpose map then map - else Operator_purpose_map.add purpose default map) - map - purposes - -let operator_purpose_map_encoding encoding = - let open Data_encoding in - let schema = - let open Json_schema in - let v_schema p = Data_encoding.Json.schema (encoding p) in - let v_schema_r p = root (v_schema p) in - let kind = - Object - { - properties = - List.map - (fun purpose -> - (string_of_purpose purpose, v_schema_r purpose, false, None)) - purposes; - pattern_properties = []; - additional_properties = None; - min_properties = 0; - max_properties = None; - schema_dependencies = []; - property_dependencies = []; - } - in - update (element kind) (v_schema Publish (* Dummy for definitions *)) - in - conv - ~schema - (fun map -> - let fields = - Operator_purpose_map.bindings map - |> List.map (fun (p, v) -> - (string_of_purpose p, Data_encoding.Json.construct (encoding p) v)) - in - `O fields) - (function - | `O fields -> - List.map - (fun (p, v) -> - let purpose = purpose_of_string_exn p in - (purpose, Data_encoding.Json.destruct (encoding purpose) v)) - fields - |> List.to_seq |> Operator_purpose_map.of_seq - | _ -> assert false) - Data_encoding.Json.encoding - -let operators_encoding = - operator_purpose_map_encoding (fun _ -> Signature.Public_key_hash.encoding) - -let fee_parameter_encoding purpose = - let open Data_encoding in - conv - (fun { - Injection.minimal_fees; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap; - burn_cap; - } -> - ( minimal_fees, - minimal_nanotez_per_byte, - minimal_nanotez_per_gas_unit, - force_low_fee, - fee_cap, - burn_cap )) - (fun ( minimal_fees, - minimal_nanotez_per_byte, - minimal_nanotez_per_gas_unit, - force_low_fee, - fee_cap, - burn_cap ) -> - { - minimal_fees; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap; - burn_cap; - }) - (obj6 - (dft - "minimal-fees" - ~description:"Exclude operations with lower fees" - Tez.encoding - default_minimal_fees) - (dft - "minimal-nanotez-per-byte" - ~description:"Exclude operations with lower fees per byte" - Plugin.Mempool.nanotez_enc - default_minimal_nanotez_per_byte) - (dft - "minimal-nanotez-per-gas-unit" - ~description:"Exclude operations with lower gas fees" - Plugin.Mempool.nanotez_enc - default_minimal_nanotez_per_gas_unit) - (dft - "force-low-fee" - ~description: - "Don't check that the fee is lower than the estimated default" - bool - default_force_low_fee) - (dft - "fee-cap" - ~description:"The fee cap" - Tez.encoding - (default_fee purpose)) - (dft - "burn-cap" - ~description:"The burn cap" - Tez.encoding - (default_burn purpose))) - -let fee_parameters_encoding = - operator_purpose_map_encoding fee_parameter_encoding - -let modes = [Observer; Batcher; Maintenance; Operator; Custom] - -let string_of_mode = function - | Observer -> "observer" - | Accuser -> "accuser" - | Batcher -> "batcher" - | Maintenance -> "maintenance" - | Operator -> "operator" - | Custom -> "custom" - -let mode_of_string = function - | "observer" -> Ok Observer - | "accuser" -> Ok Accuser - | "batcher" -> Ok Batcher - | "maintenance" -> Ok Maintenance - | "operator" -> Ok Operator - | "custom" -> Ok Custom - | _ -> Error [Exn (Failure "Invalid mode")] - -let description_of_mode = function - | Observer -> "Only follows the chain, reconstructs and interprets inboxes" - | Accuser -> - "Only publishes commitments for conflicts and play refutation games" - | Batcher -> "Accepts transactions in its queue and batches them on the L1" - | Maintenance -> - "Follows the chain and publishes commitments, cement and refute" - | Operator -> "Equivalent to maintenance + batcher" - | Custom -> - "In this mode, only operations that have a corresponding operator/signer \ - are injected" - -let mode_encoding = - Data_encoding.string_enum - [ - ("observer", Observer); - ("accuser", Accuser); - ("batcher", Batcher); - ("maintenance", Maintenance); - ("operator", Operator); - ("custom", Custom); - ] - -let batcher_encoding = - let open Data_encoding in - conv_with_guard - (fun { - simulate; - min_batch_elements; - min_batch_size; - max_batch_elements; - max_batch_size; - } -> - ( simulate, - min_batch_elements, - min_batch_size, - max_batch_elements, - max_batch_size )) - (fun ( simulate, - min_batch_elements, - min_batch_size, - max_batch_elements, - max_batch_size ) -> - if max_batch_size > protocol_max_batch_size then - Error - (Format.sprintf - "max_batch_size must be smaller than %d" - protocol_max_batch_size) - else if min_batch_size <= 0 then Error "min_batch_size must be positive" - else if max_batch_size < min_batch_size then - Error "max_batch_size must be greater than min_batch_size" - else if min_batch_elements <= 0 then - Error "min_batch_elements must be positive" - else if max_batch_elements < min_batch_elements then - Error "max_batch_elements must be greater than min_batch_elements" - else - Ok - { - simulate; - min_batch_elements; - min_batch_size; - max_batch_elements; - max_batch_size; - }) - @@ obj5 - (dft "simulate" bool default_batcher_simulate) - (dft "min_batch_elements" int31 default_batcher_min_batch_elements) - (dft "min_batch_size" int31 default_batcher_min_batch_size) - (dft "max_batch_elements" int31 default_batcher_max_batch_elements) - (dft "max_batch_size" int31 default_batcher_max_batch_size) - -let injector_encoding : injector Data_encoding.t = - let open Data_encoding in - conv - (fun {retention_period; attempts; injection_ttl} -> - (retention_period, attempts, injection_ttl)) - (fun (retention_period, attempts, injection_ttl) -> - if retention_period > max_injector_retention_period then - Format.ksprintf - Stdlib.failwith - "injector.retention_period should be smaller than %d" - max_injector_retention_period ; - if injection_ttl < 1 then - Stdlib.failwith "injector.injection_ttl should be at least 1" ; - {retention_period; attempts; injection_ttl}) - @@ obj3 - (dft "retention_period" uint16 default_injector.retention_period) - (dft "attempts" uint16 default_injector.attempts) - (dft "injection_ttl" uint16 default_injector.injection_ttl) - -let encoding : t Data_encoding.t = - let open Data_encoding in - conv - (fun { - sc_rollup_address; - sc_rollup_node_operators; - rpc_addr; - rpc_port; - metrics_addr; - reconnection_delay; - fee_parameters; - mode; - loser_mode; - dal_node_endpoint; - batcher; - injector; - l2_blocks_cache_size; - log_kernel_debug; - } -> - ( ( sc_rollup_address, - sc_rollup_node_operators, - rpc_addr, - rpc_port, - metrics_addr, - reconnection_delay, - fee_parameters, - mode, - loser_mode ), - ( dal_node_endpoint, - batcher, - injector, - l2_blocks_cache_size, - log_kernel_debug ) )) - (fun ( ( sc_rollup_address, - sc_rollup_node_operators, - rpc_addr, - rpc_port, - metrics_addr, - reconnection_delay, - fee_parameters, - mode, - loser_mode ), - ( dal_node_endpoint, - batcher, - injector, - l2_blocks_cache_size, - log_kernel_debug ) ) -> - { - sc_rollup_address; - sc_rollup_node_operators; - rpc_addr; - rpc_port; - metrics_addr; - reconnection_delay; - fee_parameters; - mode; - loser_mode; - dal_node_endpoint; - batcher; - injector; - l2_blocks_cache_size; - log_kernel_debug; - }) - (merge_objs - (obj9 - (req - "smart-rollup-address" - ~description:"Smart rollup address" - Protocol.Alpha_context.Sc_rollup.Address.encoding) - (req - "smart-rollup-node-operator" - ~description: - "Operators that sign operations of the smart rollup, by purpose" - operators_encoding) - (dft "rpc-addr" ~description:"RPC address" string default_rpc_addr) - (dft "rpc-port" ~description:"RPC port" uint16 default_rpc_port) - (opt "metrics-addr" ~description:"Metrics address" string) - (dft - "reconnection_delay" - ~description: - "The reconnection (to the tezos node) delay in seconds" - float - default_reconnection_delay) - (dft - "fee-parameters" - ~description: - "The fee parameters for each purpose used when injecting \ - operations in L1" - fee_parameters_encoding - default_fee_parameters) - (req - ~description:"The mode for this rollup node" - "mode" - mode_encoding) - (dft - "loser-mode" - ~description: - "If enabled, the rollup node will issue wrong commitments (for \ - test only!)" - Loser_mode.encoding - Loser_mode.no_failures)) - (obj5 - (opt "DAL node endpoint" Tezos_rpc.Encoding.uri_encoding) - (dft "batcher" batcher_encoding default_batcher) - (dft "injector" injector_encoding default_injector) - (dft "l2_blocks_cache_size" int31 default_l2_blocks_cache_size) - (dft "log-kernel-debug" Data_encoding.bool false))) - -let check_mode config = - let open Result_syntax in - let check_purposes purposes = - let missing_operators = - List.filter - (fun p -> - not (Operator_purpose_map.mem p config.sc_rollup_node_operators)) - purposes - in - if missing_operators <> [] then - let mode = string_of_mode config.mode in - let missing_operators = List.map string_of_purpose missing_operators in - tzfail - (Sc_rollup_node_errors.Missing_mode_operators {mode; missing_operators}) - else return_unit - in - let narrow_purposes purposes = - let+ () = check_purposes purposes in - let sc_rollup_node_operators = - Operator_purpose_map.filter - (fun op_purpose _ -> List.mem ~equal:Stdlib.( = ) op_purpose purposes) - config.sc_rollup_node_operators - in - {config with sc_rollup_node_operators} - in - match config.mode with - | Observer -> narrow_purposes [] - | Batcher -> narrow_purposes [Add_messages] - | Accuser -> narrow_purposes [Publish; Refute] - | Maintenance -> narrow_purposes [Publish; Cement; Refute] - | Operator -> narrow_purposes [Publish; Cement; Add_messages; Refute] - | Custom -> return config - -let refutation_player_buffer_levels = 5 - -let loser_warning_message config = - if config.loser_mode <> Loser_mode.no_failures then - Format.printf - {| -************ WARNING ************* -This rollup node is in loser mode. -This should be used for test only! -************ WARNING ************* -|} - -let save ~force ~data_dir config = - loser_warning_message config ; - let open Lwt_result_syntax in - let json = Data_encoding.Json.construct encoding config in - let config_file = config_filename ~data_dir in - let*! exists = Lwt_unix.file_exists config_file in - if exists && not force then - failwith - "Configuration file %S already exists. Use --force to overwrite." - config_file - else - let*! () = Lwt_utils_unix.create_dir data_dir in - Lwt_utils_unix.Json.write_file config_file json - -let load ~data_dir = - let open Lwt_result_syntax in - let+ json = Lwt_utils_unix.Json.read_file (config_filename ~data_dir) in - let config = Data_encoding.Json.destruct encoding json in - loser_warning_message config ; - config diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/configuration.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/configuration.mli deleted file mode 100644 index 9bb1576df0173d3d77a50677e335cd368943bcd0..0000000000000000000000000000000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/configuration.mli +++ /dev/null @@ -1,192 +0,0 @@ -(*****************************************************************************) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -(** Mode for the rollup node *) -type mode = - | Observer (** Only follows the chain and reconstructs inboxes *) - | Accuser - (** Only publishes commitments for conflicts and play refutation games *) - | Batcher (** Accept transactions in its queue and batches them on the L1 *) - | Maintenance (** Follows the chain and publishes commitments *) - | Operator (** Equivalent to maintenance + batcher *) - | Custom - (** This mode allows to tweak which operations are injected by selecting - the signers *) - -(** Purposes for operators, indicating the kind of operations that they sign. *) -type purpose = Publish | Add_messages | Cement | Timeout | Refute - -module Operator_purpose_map : Map.S with type key = purpose - -type operators = Signature.Public_key_hash.t Operator_purpose_map.t - -type fee_parameters = Injection.fee_parameter Operator_purpose_map.t - -(** Configuration for the batcher. - - Invariants: - - 0 < [min_batch_size] <= [max_batch_size] <= [protocol_max_batch_size] - - 0 < [min_batch_elements] <= [max_batch_elements] -*) -type batcher = { - simulate : bool; - (** If [true], the batcher will simulate the messages it receives, in an - incremental context, before queuing them. *) - min_batch_elements : int; - (** The minimum number elements in a batch for it to be produced when the - batcher receives new messages. *) - min_batch_size : int; - (** The minimum size in bytes of a batch for it to be produced when the - batcher receives new messages. *) - max_batch_elements : int; - (** The maximum number of elements that we can put in a batch. *) - max_batch_size : int; (** The maximum size in bytes of a batch. *) -} - -type injector = { - retention_period : int; - (** The number of blocks during which the injector will keep track of an - operation (in addition to the confirmation period). *) - attempts : int; - (** The number of attempts that will be made to inject an operation. *) - injection_ttl : int; - (** The number of blocks after which an operation that is injected but - never included is retried. *) -} - -type t = { - sc_rollup_address : Protocol.Alpha_context.Sc_rollup.t; - sc_rollup_node_operators : operators; - rpc_addr : string; - rpc_port : int; - metrics_addr : string option; - reconnection_delay : float; - fee_parameters : fee_parameters; - mode : mode; - loser_mode : Loser_mode.t; - (*DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/3718 - Decide whether we want to handle connections to multiple - Dal nodes for different slot indexes. - *) - dal_node_endpoint : Uri.t option; - batcher : batcher; - injector : injector; - l2_blocks_cache_size : int; - log_kernel_debug : bool; -} - -(** [make_purpose_map ~default purposes] constructs a purpose map from a list of - bindings [purposes], with a potential [default] value. *) -val make_purpose_map : - default:'a option -> (purpose * 'a) trace -> 'a Operator_purpose_map.t - -(** [purpose_of_string s] parses a purpose from the given string [s]. *) -val purpose_of_string : string -> purpose option - -(** [string_of_purpose p] returns a string representation of purpose [p]. *) -val string_of_purpose : purpose -> string - -(** List of possible purposes for operator specialization. *) -val purposes : purpose list - -(** [default_data_dir] is the default value for [data_dir]. *) -val default_data_dir : string - -(** [default_storage_dir] returns the default value of the storage dir - given a [data_dir]. *) -val default_storage_dir : string -> string - -(** [default_context_dir] returns the default value of the directory - for persisting the context given a [data_dir]. *) -val default_context_dir : string -> string - -(** [default_rpc_addr] is the default value for [rpc_addr]. *) -val default_rpc_addr : string - -(** [default_rpc_port] is the default value for [rpc_port]. *) -val default_rpc_port : int - -(** [default_metrics_port] is the default port for the metrics server. *) -val default_metrics_port : int - -(** [default_reconnection_delay] is the default value for [reconnection_delay]. *) -val default_reconnection_delay : float - -(** [default_fee_parameter ?purpose ()] is the default fee parameter to inject - operation on L1. If [purpose] is provided, it returns the default fee - parameter for the specific purpose. *) -val default_fee_parameter : ?purpose:purpose -> unit -> Injection.fee_parameter - -(** [default_fee_parameters] is the default fee parameters configuration build - with {!default_fee_parameter} for all purposes. *) -val default_fee_parameters : fee_parameters - -(** [default_batcher] is the default configuration parameters for the batcher. *) -val default_batcher : batcher - -(** [default_injector] is the default configuration parameters for the - injector. *) -val default_injector : injector - -(** [default_l2_blocks_cache_size] is the default number of L2 blocks that are - cached by the rollup node *) -val default_l2_blocks_cache_size : int - -(** [max_injector_retention_period] is the maximum allowed value for - [injector_retention_period]. *) -val max_injector_retention_period : int - -(** This is the list of available modes. *) -val modes : mode list - -(** [string_of_mode mode] returns a string representation of the mode [mode]. *) -val string_of_mode : mode -> string - -(** [mode_of_string s] returns the mode represented by string [s] if it exists. *) -val mode_of_string : string -> mode tzresult - -(** [description_of_mode m] returns a textual description of the mode [m]. *) -val description_of_mode : mode -> string - -(** [config_filename data_dir] returns - the configration filename from the [data_dir] *) -val config_filename : data_dir:string -> string - -(** [check_mode config] ensures the operators correspond to the chosen mode and - removes the extra ones. *) -val check_mode : t -> t tzresult - -(** Number of levels the refutation player waits until trying to play - for a game state it already played before. *) -val refutation_player_buffer_levels : int - -(** [save ~force ~data_dir configuration] writes the [configuration] file in - [data_dir]. If [force] is [true], existing configurations are - overwritten. *) -val save : force:bool -> data_dir:string -> t -> unit tzresult Lwt.t - -(** [load ~data_dir] loads a configuration stored in [data_dir]. *) -val load : data_dir:string -> t tzresult Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/dune b/src/proto_017_PtNairob/lib_sc_rollup_node/dune index 43b4526afebeb635fab84a7d73aa2f0d0ffa4019..529517c67cfa08464100eda84a9c3076a477571d 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/dune +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/dune @@ -36,6 +36,7 @@ aches aches-lwt octez-injector + octez-smart-rollup-node tezos-scoru-wasm tezos-scoru-wasm-fast tezos-crypto-dal @@ -62,4 +63,5 @@ -open Tezos_layer2_store -open Octez_crawler -open Octez_injector + -open Octez_smart_rollup_node -open Tezos_crypto_dal)) diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml index bc0d0cf333a861982d4f2e52e9e56c222505bbf5..c239e844e72bed6715efb7344785a470d06e79da 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/injector.ml @@ -79,24 +79,7 @@ module Parameters : | Refute _ -> Refute let fee_parameter node_ctxt operation = - let { - Injection.minimal_fees; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap; - burn_cap; - } = - Node_context.get_fee_parameter node_ctxt (operation_tag operation) - in - { - minimal_fees = {mutez = Tez.to_mutez minimal_fees}; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap = {mutez = Tez.to_mutez fee_cap}; - burn_cap = {mutez = Tez.to_mutez burn_cap}; - } + Node_context.get_fee_parameter node_ctxt (operation_tag operation) (* TODO: https://gitlab.com/tezos/tezos/-/issues/3459 Decide if some batches must have all the operations succeed. See diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/loser_mode.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/loser_mode.ml deleted file mode 100644 index 2cfbecea7baf39019b5b75b894d47f1ac99a6de9..0000000000000000000000000000000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/loser_mode.ml +++ /dev/null @@ -1,76 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -type failure = {level : int; message_index : int; message_tick : int64} - -let failure_encoding = - let open Data_encoding in - conv - (fun {level; message_index; message_tick} -> - (level, message_index, message_tick)) - (fun (level, message_index, message_tick) -> - {level; message_index; message_tick}) - (obj3 - (req "level" int31) - (req "message_index" int31) - (req "message_tick" int64)) - -let compare_failure {level; message_index; message_tick} f2 = - let open Compare.Int in - match compare level f2.level with - | 0 -> ( - match compare message_index f2.message_index with - | 0 -> Int64.compare message_tick f2.message_tick - | n -> n) - | n -> n - -type t = failure list - -let encoding = Data_encoding.list failure_encoding - -let no_failures = [] - -let make s = - let tokens = String.split_on_char ' ' s in - let rec chop = function - | [] | [""] -> [] - | level :: message_index :: message_tick :: rest -> - { - level = int_of_string level; - message_index = int_of_string message_index; - message_tick = Int64.of_string message_tick; - } - :: chop rest - | _ -> raise Not_found - in - try Some (chop tokens |> List.sort compare_failure) with _ -> None - -let is_failure failures ~level ~message_index = - List.filter_map - (fun f -> - if Compare.Int.(f.level = level && f.message_index = message_index) then - Some f.message_tick - else None) - failures diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/loser_mode.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/loser_mode.mli deleted file mode 100644 index 24171007e6b099163328396399fd535818316f97..0000000000000000000000000000000000000000 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/loser_mode.mli +++ /dev/null @@ -1,46 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -(** A list of failures. *) -type t - -val encoding : t Data_encoding.t - -(** [no_failures] are planned. *) -val no_failures : t - -(** [make s] parses a list of integers separated by spaces that is a - periodic sequence of triple [level message_index message_tick] - representing a failure that the rollup node is supposed to make. - This function returns [None] if the input string is not syntactically - correct. *) -val make : string -> t option - -(** [is_failure failures ~level ~message_index] returns [message_ticks] - where a failure is supposed to happen at the point - of the rollup node processing of a given inbox [level], a given - [message_index] and for all [message_ticks]. Ticks are sorted by - increasing order. *) -val is_failure : t -> level:int -> message_index:int -> int64 list diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml index 15e2f58755679328e381e7743268b4f9c00a167d..a4a84330a0584c152460fcbfb4f18f28d9cdcda5 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.ml @@ -61,6 +61,17 @@ type rw = [`Read | `Write] t type ro = [`Read] t +let () = + if + Tezos_crypto.Hashed.Smart_rollup_address.size + <> Protocol.Alpha_context.Sc_rollup.Address.size + then + Format.ksprintf + Stdlib.failwith + "Protocol %s is not compatible with rollup addresses of size %d" + Protocol.name + Tezos_crypto.Hashed.Smart_rollup_address.size + let get_operator node_ctxt purpose = Configuration.Operator_purpose_map.find purpose node_ctxt.operators @@ -177,6 +188,99 @@ let make_kernel_logger ?log_kernel_debug_file data_dir = in Lwt_io.of_fd ~close:(fun () -> Lwt_unix.close fd) ~mode:Lwt_io.Output fd +let check_fee_parameters Configuration.{fee_parameters; _} = + let check_value purpose name compare to_string mempool_default value = + if compare mempool_default value > 0 then + error_with + "Bad configuration fee_parameter.%s for %s. It must be at least %s for \ + operations of the injector to be propagated." + name + (Configuration.string_of_purpose purpose) + (to_string mempool_default) + else Ok () + in + let check purpose + { + Injector_sigs.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee = _; + fee_cap = _; + burn_cap = _; + } = + let open Result_syntax in + let+ () = + check_value + purpose + "minimal_fees" + Int64.compare + Int64.to_string + (Tez.to_mutez Plugin.Mempool.default_minimal_fees) + minimal_fees.mutez + and+ () = + check_value + purpose + "minimal_nanotez_per_byte" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_byte + minimal_nanotez_per_byte + and+ () = + check_value + purpose + "minimal_nanotez_per_gas_unit" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_gas_unit + minimal_nanotez_per_gas_unit + in + () + in + Configuration.Operator_purpose_map.iter_e check fee_parameters + +let protocol_max_batch_size = + let empty_message_op : _ Operation.t = + let open Protocol in + let open Alpha_context in + let open Operation in + { + shell = {branch = Block_hash.zero}; + protocol_data = + { + signature = Some Signature.zero; + contents = + Single + (Manager_operation + { + source = Signature.Public_key_hash.zero; + fee = Tez.of_mutez_exn Int64.max_int; + counter = Manager_counter.Internal_for_tests.of_int max_int; + gas_limit = + Gas.Arith.integral_of_int_exn ((max_int - 1) / 1000); + storage_limit = Z.of_int max_int; + operation = Sc_rollup_add_messages {messages = [""]}; + }); + }; + } + in + Protocol.Constants_repr.max_operation_data_length + - Data_encoding.Binary.length + Operation.encoding + (Operation.pack empty_message_op) + +let check_batcher_config Configuration.{batcher = {max_batch_size; _}; _} = + match max_batch_size with + | Some m when m > protocol_max_batch_size -> + error_with + "batcher.max_batch_size must be smaller than %d" + protocol_max_batch_size + | _ -> Ok () + +let check_config config = + let open Result_syntax in + let+ () = check_fee_parameters config and+ () = check_batcher_config config in + () + let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file mode Configuration.( @@ -192,6 +296,12 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file _; } as configuration) = let open Lwt_result_syntax in + let*? () = check_config configuration in + let rollup_address = + (* Convert to protocol rollup address *) + Tezos_crypto.Hashed.Smart_rollup_address.to_bytes rollup_address + |> Protocol.Alpha_context.Sc_rollup.Address.of_bytes_exn + in let* lockfile = lock ~data_dir in let dal_cctxt = Option.map Dal_node_client.make_unix_cctxt dal_node_endpoint @@ -221,7 +331,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file and* genesis_info = RPC.Sc_rollup.genesis_info cctxt (cctxt#chain, cctxt#block) rollup_address in - let*! () = Event.rollup_exists ~addr:configuration.sc_rollup_address ~kind in + let*! () = Event.rollup_exists ~addr:rollup_address ~kind in let*! () = if dal_cctxt = None && protocol_constants.parametric.dal.feature_enable then Event.warn_dal_enabled_no_node () diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli index 37cdd1cd9aac2f30cef7400317f0a852cdc210bf..713cf00c6502c143272c4508442df63aea3027c9 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/node_context.mli @@ -109,7 +109,12 @@ val is_loser : _ t -> bool configured for this purpose, returns the default fee parameter for this purpose. *) -val get_fee_parameter : _ t -> Configuration.purpose -> Injection.fee_parameter +val get_fee_parameter : + _ t -> Configuration.purpose -> Injector_sigs.fee_parameter + +(** Maximum size of an L2 batch in bytes that can fit in an operation of the + protocol. *) +val protocol_max_batch_size : int (** [init cctxt ~data_dir mode configuration] initializes the rollup representation. The rollup origination level and kind are fetched via an RPC diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/sc_rollup_node_errors.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/sc_rollup_node_errors.ml index 344aa528c00db39c5832cbaa0074a9acae2a78c8..75f4fd02e92bcce2c9c4b6ffb75a0d5ccc25fca1 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/sc_rollup_node_errors.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/sc_rollup_node_errors.ml @@ -31,7 +31,6 @@ let register_error_kind ~id = register_error_kind ~id:(make_id id) type error += | Cannot_produce_proof of Sc_rollup.Game.t - | Missing_mode_operators of {mode : string; missing_operators : string list} | Bad_minimal_fees of string | Disagree_with_cemented of { inbox_level : Raw_level.t; @@ -144,29 +143,6 @@ let () = (function Cannot_produce_proof game -> Some game | _ -> None) (fun game -> Cannot_produce_proof game) ; - register_error_kind - ~id:"sc_rollup.node.missing_mode_operators" - ~title:"Missing operators for the chosen mode" - ~description:"Missing operators for the chosen mode." - ~pp:(fun ppf (mode, missing_operators) -> - Format.fprintf - ppf - "@[Missing operators %a for mode %s.@]" - (Format.pp_print_list - ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ") - Format.pp_print_string) - missing_operators - mode) - `Permanent - Data_encoding.( - obj2 (req "mode" string) (req "missing_operators" (list string))) - (function - | Missing_mode_operators {mode; missing_operators} -> - Some (mode, missing_operators) - | _ -> None) - (fun (mode, missing_operators) -> - Missing_mode_operators {mode; missing_operators}) ; - register_error_kind ~id:"sc_rollup.node.Wrong_initial_pvm_state" ~title:"Initial state produced by PVM is incorrect" diff --git a/src/proto_alpha/bin_sc_rollup_node/dune b/src/proto_alpha/bin_sc_rollup_node/dune index d2f76e93346ee205a7b2a1982b7e7b3a9551214b..9cae4b7bc5dea9444efebec7339f346223ecb683 100644 --- a/src/proto_alpha/bin_sc_rollup_node/dune +++ b/src/proto_alpha/bin_sc_rollup_node/dune @@ -15,6 +15,7 @@ tezos-client-base-unix tezos-client-commands tezos-client-alpha + octez-smart-rollup-node octez_smart_rollup_node_alpha) (link_flags (:standard) @@ -31,4 +32,5 @@ -open Tezos_client_base_unix -open Tezos_client_commands -open Tezos_client_alpha + -open Octez_smart_rollup_node -open Octez_smart_rollup_node_alpha)) diff --git a/src/proto_alpha/lib_sc_rollup_node/batcher.ml b/src/proto_alpha/lib_sc_rollup_node/batcher.ml index f2090acd06976860d79c7b7cca7279a2017fb4be..d317880cb45d843a14cba0862d77eb39dfcd8257 100644 --- a/src/proto_alpha/lib_sc_rollup_node/batcher.ml +++ b/src/proto_alpha/lib_sc_rollup_node/batcher.ml @@ -71,10 +71,19 @@ module Make (Simulation : Simulation.S) : S = struct type status = Pending_batch | Batched of Injector.Inj_operation.hash + (* Same as {!Configuration.batcher} with max_batch_size non optional. *) + type conf = { + simulate : bool; + min_batch_elements : int; + min_batch_size : int; + max_batch_elements : int; + max_batch_size : int; + } + type state = { node_ctxt : Node_context.ro; signer : Signature.public_key_hash; - conf : Configuration.batcher; + conf : conf; messages : Message_queue.t; batched : Batched_messages.t; mutable simulation_ctxt : Simulation.t option; @@ -249,8 +258,20 @@ module Make (Simulation : Simulation.S) : S = struct (* Forget failing messages *) List.iter (Message_queue.remove state.messages) failing - let init_batcher_state node_ctxt ~signer conf = + let init_batcher_state node_ctxt ~signer (conf : Configuration.batcher) = let open Lwt_syntax in + let conf = + { + simulate = conf.simulate; + min_batch_elements = conf.min_batch_elements; + min_batch_size = conf.min_batch_size; + max_batch_elements = conf.max_batch_elements; + max_batch_size = + Option.value + conf.max_batch_size + ~default:Node_context.protocol_max_batch_size; + } + in return { node_ctxt; diff --git a/src/proto_alpha/lib_sc_rollup_node/dune b/src/proto_alpha/lib_sc_rollup_node/dune index b1e180583a171023bbe631ad15646261f8a8ee0f..553a49ac3e9466c6161513e4c6daaa7c2fe780b2 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dune +++ b/src/proto_alpha/lib_sc_rollup_node/dune @@ -37,6 +37,7 @@ aches aches-lwt octez-injector + octez-smart-rollup-node tezos-scoru-wasm tezos-scoru-wasm-fast tezos-crypto-dal @@ -64,4 +65,5 @@ -open Tezos_layer2_store -open Octez_crawler -open Octez_injector + -open Octez_smart_rollup_node -open Tezos_crypto_dal)) diff --git a/src/proto_alpha/lib_sc_rollup_node/injector.ml b/src/proto_alpha/lib_sc_rollup_node/injector.ml index 9616f61914057abee296edb01e18aa3de10424fd..9f128729bb9ffd30a6d0592f6d85499eaed8d140 100644 --- a/src/proto_alpha/lib_sc_rollup_node/injector.ml +++ b/src/proto_alpha/lib_sc_rollup_node/injector.ml @@ -79,24 +79,7 @@ module Parameters : | Refute _ -> Refute let fee_parameter node_ctxt operation = - let { - Injection.minimal_fees; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap; - burn_cap; - } = - Node_context.get_fee_parameter node_ctxt (operation_tag operation) - in - { - minimal_fees = {mutez = Tez.to_mutez minimal_fees}; - minimal_nanotez_per_byte; - minimal_nanotez_per_gas_unit; - force_low_fee; - fee_cap = {mutez = Tez.to_mutez fee_cap}; - burn_cap = {mutez = Tez.to_mutez burn_cap}; - } + Node_context.get_fee_parameter node_ctxt (operation_tag operation) (* TODO: https://gitlab.com/tezos/tezos/-/issues/3459 Decide if some batches must have all the operations succeed. See diff --git a/src/proto_alpha/lib_sc_rollup_node/loser_mode.ml b/src/proto_alpha/lib_sc_rollup_node/loser_mode.ml deleted file mode 100644 index 2cfbecea7baf39019b5b75b894d47f1ac99a6de9..0000000000000000000000000000000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/loser_mode.ml +++ /dev/null @@ -1,76 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -type failure = {level : int; message_index : int; message_tick : int64} - -let failure_encoding = - let open Data_encoding in - conv - (fun {level; message_index; message_tick} -> - (level, message_index, message_tick)) - (fun (level, message_index, message_tick) -> - {level; message_index; message_tick}) - (obj3 - (req "level" int31) - (req "message_index" int31) - (req "message_tick" int64)) - -let compare_failure {level; message_index; message_tick} f2 = - let open Compare.Int in - match compare level f2.level with - | 0 -> ( - match compare message_index f2.message_index with - | 0 -> Int64.compare message_tick f2.message_tick - | n -> n) - | n -> n - -type t = failure list - -let encoding = Data_encoding.list failure_encoding - -let no_failures = [] - -let make s = - let tokens = String.split_on_char ' ' s in - let rec chop = function - | [] | [""] -> [] - | level :: message_index :: message_tick :: rest -> - { - level = int_of_string level; - message_index = int_of_string message_index; - message_tick = Int64.of_string message_tick; - } - :: chop rest - | _ -> raise Not_found - in - try Some (chop tokens |> List.sort compare_failure) with _ -> None - -let is_failure failures ~level ~message_index = - List.filter_map - (fun f -> - if Compare.Int.(f.level = level && f.message_index = message_index) then - Some f.message_tick - else None) - failures diff --git a/src/proto_alpha/lib_sc_rollup_node/loser_mode.mli b/src/proto_alpha/lib_sc_rollup_node/loser_mode.mli deleted file mode 100644 index 24171007e6b099163328396399fd535818316f97..0000000000000000000000000000000000000000 --- a/src/proto_alpha/lib_sc_rollup_node/loser_mode.mli +++ /dev/null @@ -1,46 +0,0 @@ -(*****************************************************************************) -(* *) -(* Open Source License *) -(* Copyright (c) 2022 Nomadic Labs, *) -(* *) -(* 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. *) -(* *) -(*****************************************************************************) - -(** A list of failures. *) -type t - -val encoding : t Data_encoding.t - -(** [no_failures] are planned. *) -val no_failures : t - -(** [make s] parses a list of integers separated by spaces that is a - periodic sequence of triple [level message_index message_tick] - representing a failure that the rollup node is supposed to make. - This function returns [None] if the input string is not syntactically - correct. *) -val make : string -> t option - -(** [is_failure failures ~level ~message_index] returns [message_ticks] - where a failure is supposed to happen at the point - of the rollup node processing of a given inbox [level], a given - [message_index] and for all [message_ticks]. Ticks are sorted by - increasing order. *) -val is_failure : t -> level:int -> message_index:int -> int64 list diff --git a/src/proto_alpha/lib_sc_rollup_node/node_context.ml b/src/proto_alpha/lib_sc_rollup_node/node_context.ml index 9d151d780dfce82efbb67a86e0daace2958be5bc..4c04fe2013dc46c0ea67dde724ac86425475f40a 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.ml @@ -179,6 +179,99 @@ let make_kernel_logger ?log_kernel_debug_file data_dir = in Lwt_io.of_fd ~close:(fun () -> Lwt_unix.close fd) ~mode:Lwt_io.Output fd +let check_fee_parameters Configuration.{fee_parameters; _} = + let check_value purpose name compare to_string mempool_default value = + if compare mempool_default value > 0 then + error_with + "Bad configuration fee_parameter.%s for %s. It must be at least %s for \ + operations of the injector to be propagated." + name + (Configuration.string_of_purpose purpose) + (to_string mempool_default) + else Ok () + in + let check purpose + { + Injector_sigs.minimal_fees; + minimal_nanotez_per_byte; + minimal_nanotez_per_gas_unit; + force_low_fee = _; + fee_cap = _; + burn_cap = _; + } = + let open Result_syntax in + let+ () = + check_value + purpose + "minimal_fees" + Int64.compare + Int64.to_string + (Tez.to_mutez Plugin.Mempool.default_minimal_fees) + minimal_fees.mutez + and+ () = + check_value + purpose + "minimal_nanotez_per_byte" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_byte + minimal_nanotez_per_byte + and+ () = + check_value + purpose + "minimal_nanotez_per_gas_unit" + Q.compare + Q.to_string + Plugin.Mempool.default_minimal_nanotez_per_gas_unit + minimal_nanotez_per_gas_unit + in + () + in + Configuration.Operator_purpose_map.iter_e check fee_parameters + +let protocol_max_batch_size = + let empty_message_op : _ Operation.t = + let open Protocol in + let open Alpha_context in + let open Operation in + { + shell = {branch = Block_hash.zero}; + protocol_data = + { + signature = Some Signature.zero; + contents = + Single + (Manager_operation + { + source = Signature.Public_key_hash.zero; + fee = Tez.of_mutez_exn Int64.max_int; + counter = Manager_counter.Internal_for_tests.of_int max_int; + gas_limit = + Gas.Arith.integral_of_int_exn ((max_int - 1) / 1000); + storage_limit = Z.of_int max_int; + operation = Sc_rollup_add_messages {messages = [""]}; + }); + }; + } + in + Protocol.Constants_repr.max_operation_data_length + - Data_encoding.Binary.length + Operation.encoding_with_legacy_attestation_name + (Operation.pack empty_message_op) + +let check_batcher_config Configuration.{batcher = {max_batch_size; _}; _} = + match max_batch_size with + | Some m when m > protocol_max_batch_size -> + error_with + "batcher.max_batch_size must be smaller than %d" + protocol_max_batch_size + | _ -> Ok () + +let check_config config = + let open Result_syntax in + let+ () = check_fee_parameters config and+ () = check_batcher_config config in + () + let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file mode Configuration.( @@ -195,6 +288,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file _; } as configuration) = let open Lwt_result_syntax in + let*? () = check_config configuration in let* lockfile = lock ~data_dir in let dal_cctxt = Option.map Dal_node_client.make_unix_cctxt dal_node_endpoint @@ -224,7 +318,7 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file and* genesis_info = RPC.Sc_rollup.genesis_info cctxt (cctxt#chain, cctxt#block) rollup_address in - let*! () = Event.rollup_exists ~addr:configuration.sc_rollup_address ~kind in + let*! () = Event.rollup_exists ~addr:rollup_address ~kind in let*! () = if dal_cctxt = None && protocol_constants.parametric.dal.feature_enable then Event.warn_dal_enabled_no_node () diff --git a/src/proto_alpha/lib_sc_rollup_node/node_context.mli b/src/proto_alpha/lib_sc_rollup_node/node_context.mli index a1f89c7a157557632bd66722c14e92b55796ab8d..518ea15b92402c79f53f0447b9d3eaddf652fdd8 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.mli +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.mli @@ -114,7 +114,12 @@ val is_loser : _ t -> bool configured for this purpose, returns the default fee parameter for this purpose. *) -val get_fee_parameter : _ t -> Configuration.purpose -> Injection.fee_parameter +val get_fee_parameter : + _ t -> Configuration.purpose -> Injector_sigs.fee_parameter + +(** Maximum size of an L2 batch in bytes that can fit in an operation of the + protocol. *) +val protocol_max_batch_size : int (** [init cctxt ~data_dir mode configuration] initializes the rollup representation. The rollup origination level and kind are fetched via an RPC diff --git a/src/proto_alpha/lib_sc_rollup_node/sc_rollup_node_errors.ml b/src/proto_alpha/lib_sc_rollup_node/sc_rollup_node_errors.ml index 0361e546f15c12b47a8b89923ca2ba5cae1ab7d6..6f88c4fb3f80c919a8955b1cef30b1d131a106a4 100644 --- a/src/proto_alpha/lib_sc_rollup_node/sc_rollup_node_errors.ml +++ b/src/proto_alpha/lib_sc_rollup_node/sc_rollup_node_errors.ml @@ -31,7 +31,6 @@ let register_error_kind ~id = register_error_kind ~id:(make_id id) type error += | Cannot_produce_proof of Sc_rollup.Game.t - | Missing_mode_operators of {mode : string; missing_operators : string list} | Bad_minimal_fees of string | Disagree_with_cemented of { inbox_level : Raw_level.t; @@ -145,29 +144,6 @@ let () = (function Cannot_produce_proof game -> Some game | _ -> None) (fun game -> Cannot_produce_proof game) ; - register_error_kind - ~id:"sc_rollup.node.missing_mode_operators" - ~title:"Missing operators for the chosen mode" - ~description:"Missing operators for the chosen mode." - ~pp:(fun ppf (mode, missing_operators) -> - Format.fprintf - ppf - "@[Missing operators %a for mode %s.@]" - (Format.pp_print_list - ~pp_sep:(fun ppf () -> Format.fprintf ppf ",@ ") - Format.pp_print_string) - missing_operators - mode) - `Permanent - Data_encoding.( - obj2 (req "mode" string) (req "missing_operators" (list string))) - (function - | Missing_mode_operators {mode; missing_operators} -> - Some (mode, missing_operators) - | _ -> None) - (fun (mode, missing_operators) -> - Missing_mode_operators {mode; missing_operators}) ; - register_error_kind ~id:"sc_rollup.node.Wrong_initial_pvm_state" ~title:"Initial state produced by PVM is incorrect"