diff --git a/etherlink/bin_node/config/configuration.ml b/etherlink/bin_node/config/configuration.ml index d767d8cd9c059ce20b17963912296844d13a0a2a..cd8d184e77365e43c10059f38f2456556aca72e3 100644 --- a/etherlink/bin_node/config/configuration.ml +++ b/etherlink/bin_node/config/configuration.ml @@ -44,7 +44,7 @@ type garbage_collector_parameters = { number_of_chunks : int; } -type history_mode = Archive | Rolling +type history_mode = Archive | Rolling of garbage_collector_parameters type rpc_server = Resto | Dream @@ -133,7 +133,6 @@ type t = { experimental_features : experimental_features; fee_history : fee_history; finalized_view : bool; - garbage_collector_parameters : garbage_collector_parameters; history_mode : history_mode option; } @@ -148,10 +147,25 @@ let default_enable_send_raw_transaction = true let default_history_mode = Archive -let retention ?(days = 14) () = +let gc_param_from_retention_period ~days = {split_frequency_in_seconds = 86_400; number_of_chunks = days} -let default_garbage_collector_parameters = retention () +let history_mode_of_string_opt str = + let open Option_syntax in + match String.split_on_char ':' str with + | ["archive"] -> return Archive + | ["rolling"; days] -> + let* days = int_of_string_opt days in + if days > 0 then return (Rolling (gc_param_from_retention_period ~days)) + else None + | _ -> None + +let string_of_history_mode = function + | Archive -> "archive" + | Rolling gc -> Format.sprintf "rolling:%d" gc.number_of_chunks + +let pp_history_mode fmt h = + Format.pp_print_string fmt @@ string_of_history_mode h (* This should be enough for messages we expect to receive in the ethereum JSONRPC protocol. *) @@ -717,68 +731,30 @@ let observer_encoding ?network () = bool default_rollup_node_tracking)) -let garbage_collector_parameters_encoding = - let open Data_encoding in - let int_days = - def - "days" - ~title:"number_of_days" - ~description:"Number of days of history to retain" - (ranged_int 0 ((1 lsl 30) - 1)) - in - conv - (function - | {split_frequency_in_seconds = 86_400; number_of_chunks} -> - number_of_chunks - | _ -> Stdlib.failwith "GC split frequency must one day") - (fun number_of_chunks -> - {split_frequency_in_seconds = 86_400; number_of_chunks}) - int_days - let rpc_server_encoding = let open Data_encoding in string_enum [("resto", Resto); ("dream", Dream)] -let history_mode_encoding = - let open Data_encoding in - string_enum [("archive", Archive); ("rolling", Rolling)] - -let pp_history_mode fmt h = - Format.pp_print_string fmt - @@ match h with Archive -> "archive" | Rolling -> "rolling" +let history_mode_schema = + Data_encoding.( + Json.schema @@ string_enum [("archive", ()); ("rolling:n", ())]) -let history_mode_and_gc_parameters_encoding = +let history_mode_encoding = let open Data_encoding in - union - [ - case - ~title:"archive" - (Tag 0) - (constant "archive") - (function Archive, _ -> Some () | _ -> None) - (fun () -> (Archive, default_garbage_collector_parameters)); - case - ~title:"rolling_default_gc" - (Tag 1) - (constant "rolling") - (function - | _ -> - (* This is a shortcut for rolling with default GC parameters, - never output it. *) - None) - (fun () -> (Rolling, default_garbage_collector_parameters)); - case - ~title:"rolling" - (Tag 2) - (obj2 - (req "mode" (constant "rolling")) - (req - "retention" - ~description:"How much history is retained for rolling nodes." - garbage_collector_parameters_encoding)) - (function Rolling, gc -> Some ((), gc) | _ -> None) - (fun ((), gc) -> (Rolling, gc)); - ] + def + "history_mode" + ~description: + "Compact notation for the history mode. Can either be `archive` and \ + `rolling:N` with `N` being the number of days to use as the retention \ + period" + @@ conv_with_guard + ~schema:history_mode_schema + string_of_history_mode + (fun str -> + match history_mode_of_string_opt str with + | None -> Error (Format.sprintf "%s is not a valid history mode" str) + | Some m -> Ok m) + string let monitor_websocket_heartbeat_encoding = let open Data_encoding in @@ -1165,7 +1141,6 @@ let encoding ?network data_dir : t Data_encoding.t = kernel_execution; finalized_view; history_mode; - garbage_collector_parameters; } -> ( (log_filter, sequencer, threshold_encryption_sequencer, observer), ( ( tx_pool_timeout_limit, @@ -1181,9 +1156,7 @@ let encoding ?network data_dir : t Data_encoding.t = public_rpc, private_rpc, finalized_view, - match history_mode with - | Some h -> Some (h, garbage_collector_parameters) - | None -> None ) ) )) + history_mode ) ) )) (fun ( (log_filter, sequencer, threshold_encryption_sequencer, observer), ( ( tx_pool_timeout_limit, tx_pool_addr_limit, @@ -1198,12 +1171,7 @@ let encoding ?network data_dir : t Data_encoding.t = public_rpc, private_rpc, finalized_view, - history_mode_and_gc ) ) ) -> - let history_mode, garbage_collector_parameters = - match history_mode_and_gc with - | None -> (None, default_garbage_collector_parameters) - | Some (h, gc) -> (Some h, gc) - in + history_mode ) ) ) -> { public_rpc; private_rpc; @@ -1223,7 +1191,6 @@ let encoding ?network data_dir : t Data_encoding.t = kernel_execution; finalized_view; history_mode; - garbage_collector_parameters; }) (merge_objs (obj4 @@ -1303,7 +1270,7 @@ let encoding ?network data_dir : t Data_encoding.t = (opt "history" ~description:"History mode of the EVM node" - history_mode_and_gc_parameters_encoding)))) + history_mode_encoding)))) let pp_print_json ~data_dir fmt config = let json = @@ -1486,8 +1453,7 @@ module Cli = struct ?log_filter_max_nb_logs ?log_filter_chunk_size ?max_blueprints_lag ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown ?sequencer_sidecar_endpoint ?restricted_rpcs ?finalized_view - ?proxy_ignore_block_param ?dal_slots ?network ?history_mode - ?garbage_collector_parameters () = + ?proxy_ignore_block_param ?dal_slots ?network ?history_mode () = let public_rpc = default_rpc ?rpc_port @@ -1596,10 +1562,6 @@ module Cli = struct fee_history = default_fee_history; finalized_view = Option.value ~default:default_finalized_view finalized_view; - garbage_collector_parameters = - Option.value - garbage_collector_parameters - ~default:default_garbage_collector_parameters; history_mode; } @@ -1642,8 +1604,7 @@ module Cli = struct ?log_filter_max_nb_logs ?log_filter_chunk_size ?max_blueprints_lag ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown ?sequencer_sidecar_endpoint ?restricted_rpcs ?finalized_view - ?proxy_ignore_block_param ?history_mode ?garbage_collector_parameters - ?dal_slots configuration = + ?proxy_ignore_block_param ?history_mode ?dal_slots configuration = let public_rpc = patch_rpc ?rpc_addr @@ -1901,10 +1862,6 @@ module Cli = struct experimental_features = configuration.experimental_features; fee_history = configuration.fee_history; finalized_view = finalized_view || configuration.finalized_view; - garbage_collector_parameters = - Option.value - garbage_collector_parameters - ~default:configuration.garbage_collector_parameters; history_mode = Option.either history_mode configuration.history_mode; } @@ -1918,8 +1875,7 @@ module Cli = struct ?max_blueprints_ahead ?max_blueprints_catchup ?catchup_cooldown ?log_filter_max_nb_blocks ?log_filter_max_nb_logs ?log_filter_chunk_size ?sequencer_sidecar_endpoint ?restricted_rpcs ?finalized_view - ?proxy_ignore_block_param ?dal_slots ?network ?history_mode - ?garbage_collector_parameters () = + ?proxy_ignore_block_param ?dal_slots ?network ?history_mode () = let open Lwt_result_syntax in let open Filename.Infix in (* Check if the data directory of the evm node is not the one of Octez @@ -1975,7 +1931,6 @@ module Cli = struct ?finalized_view ?proxy_ignore_block_param ?history_mode - ?garbage_collector_parameters ?dal_slots configuration in @@ -2019,7 +1974,6 @@ module Cli = struct ?dal_slots ?network ?history_mode - ?garbage_collector_parameters () in return config diff --git a/etherlink/bin_node/config/configuration.mli b/etherlink/bin_node/config/configuration.mli index f4019620ec0916fdb698d4512f7f60a5ed506815..dcfa19faabd14cf945d179036db976f9257e0092 100644 --- a/etherlink/bin_node/config/configuration.mli +++ b/etherlink/bin_node/config/configuration.mli @@ -66,7 +66,7 @@ type garbage_collector_parameters = { type history_mode = | Archive (** Keeps all blocks, operations and states. *) - | Rolling + | Rolling of garbage_collector_parameters (** Keep blocks, operations and states for a period defined by {!type-garbage_collector_parameters}. *) @@ -170,7 +170,6 @@ type t = { experimental_features : experimental_features; fee_history : fee_history; finalized_view : bool; - garbage_collector_parameters : garbage_collector_parameters; history_mode : history_mode option; } @@ -261,9 +260,13 @@ val observer_config_dft : val make_pattern_restricted_rpcs : string -> restricted_rpcs -(** [retention ?days ()] returns the GC parameters to retain [days] of history +val string_of_history_mode : history_mode -> string + +val history_mode_of_string_opt : string -> history_mode option + +(** [retention ~days] returns the GC parameters to retain [days] of history when provided or the default otherwise. *) -val retention : ?days:int -> unit -> garbage_collector_parameters +val gc_param_from_retention_period : days:int -> garbage_collector_parameters val default_history_mode : history_mode @@ -305,7 +308,6 @@ module Cli : sig ?dal_slots:int list -> ?network:supported_network -> ?history_mode:history_mode -> - ?garbage_collector_parameters:garbage_collector_parameters -> unit -> t @@ -343,7 +345,6 @@ module Cli : sig ?finalized_view:bool -> ?proxy_ignore_block_param:bool -> ?history_mode:history_mode -> - ?garbage_collector_parameters:garbage_collector_parameters -> ?dal_slots:int list -> t -> t @@ -385,7 +386,6 @@ module Cli : sig ?dal_slots:int list -> ?network:supported_network -> ?history_mode:history_mode -> - ?garbage_collector_parameters:garbage_collector_parameters -> unit -> t tzresult Lwt.t end diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 99b11853ce407c1a399ca9defc84215b1bdcae0a..fb0a6147b1280328ac6d43bb378d48ea96a80d24 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -310,7 +310,7 @@ module State = struct let* history_mode = Evm_store.Metadata.get_history_mode conn in match history_mode with | Archive -> return_none - | Rolling -> + | Rolling gc_param -> let split = match ctxt.session.last_split_block with | None -> true @@ -324,18 +324,14 @@ module State = struct >= Int64.( add last_split_timestamp - (of_int - ctxt.configuration.garbage_collector_parameters - .split_frequency_in_seconds))) + (of_int gc_param.split_frequency_in_seconds))) in if split then ( Irmin_context.split ctxt.index ; let* () = Evm_store.Irmin_chunks.insert conn level timestamp in let*! () = Evm_context_events.gc_split level timestamp in let* number_of_chunks = Evm_store.Irmin_chunks.count conn in - let max_number_of_chunks = - ctxt.configuration.garbage_collector_parameters.number_of_chunks - in + let max_number_of_chunks = gc_param.number_of_chunks in let* () = if number_of_chunks > max_number_of_chunks then let* gc_level, _gc_timestamp = @@ -1144,51 +1140,42 @@ module State = struct *) return Tezos_crypto.Hashed.Smart_rollup_address.zero - let check_history_mode ?(switch = false) ~store_history_mode ~history_mode - conn = + let history_mode_switch_status h1 h2 = + let open Configuration in + match (h1, h2) with + | Archive, Archive -> `No_switch + | Rolling gc, Rolling gc' when gc.number_of_chunks = gc'.number_of_chunks -> + `No_switch + | Rolling _, Rolling _ | Archive, Rolling _ -> `Needs_switch + | Rolling _, Archive -> `Cannot_switch + + let check_history_mode ?(switch = false) ~store_history_mode ~history_mode () + = let open Lwt_result_syntax in - match store_history_mode with - | None -> ( - match history_mode with - | None -> return Configuration.default_history_mode - | Some h -> return h) - | Some store_history_mode -> ( - match (store_history_mode, history_mode) with - | Configuration.Archive, (None | Some Archive) - | Rolling, (None | Some Rolling) -> + match (store_history_mode, history_mode) with + | Some h, None -> return h + | None, None -> return Configuration.default_history_mode + | None, Some h -> return h + | Some store_history_mode, Some history_mode -> ( + match history_mode_switch_status store_history_mode history_mode with + | `No_switch -> if switch then Format.printf "History mode is already %a, not switching@." Configuration.pp_history_mode store_history_mode ; return store_history_mode - | Archive, Some Rolling when switch -> + | `Needs_switch when switch -> let*! () = Evm_context_events.switching_history_mode - ~from:Archive - ~to_:Rolling + ~from:store_history_mode + ~to_:history_mode in - return Configuration.Rolling - | Rolling, Some Archive when switch -> - (* Switching from rolling to archive is possible, however it does - not necessarily mean all information are stored, it will just - stop garbage collecting data. *) - let* () = Evm_store.Irmin_chunks.clear conn in - let* earliest = Evm_store.Context_hashes.find_earliest conn in - let earliest_level = Option.map fst earliest in - let* () = - unless (earliest_level = Some Ethereum_types.Qty.zero) (fun () -> - let*! () = - Evm_context_events.rolling_to_archive_incomplete_history - earliest_level - in - return_unit) - in - return Configuration.Archive - | _, Some history_mode -> + return history_mode + | _ -> tzfail (Incorrect_history_mode {store_history_mode; history_mode})) - let check_metadata ~store_metadata ~smart_rollup_address ~history_mode conn = + let check_metadata ~store_metadata ~smart_rollup_address ~history_mode () = let open Lwt_result_syntax in let* smart_rollup_address = check_smart_rollup_address @@ -1206,7 +1193,7 @@ module State = struct (fun (metadata : Evm_store.metadata) -> metadata.history_mode) store_metadata) ~history_mode - conn + () in return ({smart_rollup_address; history_mode} : Evm_store.metadata) @@ -1290,7 +1277,7 @@ module State = struct ~store_metadata ~smart_rollup_address ~history_mode:configuration.history_mode - conn + () in let* () = when_ (Option.is_none store_metadata) (fun () -> @@ -1325,7 +1312,7 @@ module State = struct let* last_split_block = match history_mode with - | Rolling -> Evm_store.Irmin_chunks.latest conn + | Rolling _ -> Evm_store.Irmin_chunks.latest conn | Archive -> return_none in diff --git a/etherlink/bin_node/lib_dev/evm_context.mli b/etherlink/bin_node/lib_dev/evm_context.mli index 43fbc79319dad3d17bccdc6f8b185b0c78ef9bc0..903acdb636e6c887a150460611e59c43e18cea2f 100644 --- a/etherlink/bin_node/lib_dev/evm_context.mli +++ b/etherlink/bin_node/lib_dev/evm_context.mli @@ -140,7 +140,7 @@ val head_watcher : Ethereum_types.Subscription.output Lwt_watcher.input (** Watcher that gets notified each time a new receipt is produced. *) val receipt_watcher : Transaction_receipt.t Lwt_watcher.input -(** [check_history_mode ?switch ~store_history_mode ~history_mode conn] checks +(** [check_history_mode ?switch ~store_history_mode ~history_mode ()] checks that the history mode are compatible, and returns the history mode the node should run in, depending on its stored mode [store_history_mode], the one requested by the configuration [history_mode] and if it is allowed to @@ -149,5 +149,5 @@ val check_history_mode : ?switch:bool -> store_history_mode:Configuration.history_mode option -> history_mode:Configuration.history_mode option -> - Sqlite.conn -> + unit -> Configuration.history_mode tzresult Lwt.t diff --git a/etherlink/bin_node/lib_dev/evm_store.ml b/etherlink/bin_node/lib_dev/evm_store.ml index 41466161b9f9c69150e718d257f5a1c9df2398b0..ff7087df99099b99ed8d191b5cc277e80922566a 100644 --- a/etherlink/bin_node/lib_dev/evm_store.ml +++ b/etherlink/bin_node/lib_dev/evm_store.ml @@ -161,12 +161,11 @@ module Q = struct let history_mode = custom - ~encode:(function - | Configuration.Archive -> Ok "archive" | Rolling -> Ok "rolling") - ~decode:(function - | "archive" -> Ok Archive - | "rolling" -> Ok Rolling - | s -> Error (Format.sprintf "Cannot decode %S" s)) + ~encode:(fun mode -> Ok (Configuration.string_of_history_mode mode)) + ~decode:(fun str -> + Option.to_result + ~none:(Format.sprintf "Cannot decode %S" str) + Configuration.(history_mode_of_string_opt str)) string let levels = @@ -235,7 +234,7 @@ module Q = struct You can review the result at [etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- debug print store schemas.out]. *) - let version = 17 + let version = 18 let all : Evm_node_migrations.migration list = Evm_node_migrations.migrations version diff --git a/etherlink/bin_node/main.ml b/etherlink/bin_node/main.ml index b82cfe05c74f1c91a69a608dc1002336147ee044..a86d42ce275daf3cf89d7b3ad6a9d3acf0277f43 100644 --- a/etherlink/bin_node/main.ml +++ b/etherlink/bin_node/main.ml @@ -162,29 +162,19 @@ module Params = struct let history_param = Tezos_clic.parameter @@ fun () s -> let open Lwt_result_syntax in - match String.split_on_char ':' s with - | ["archive"] -> return Configuration.(Archive, retention ()) - | ["rolling"] -> return Configuration.(Rolling, retention ()) - | ["rolling"; n] -> ( - match int_of_string_opt n with - | Some days when days >= 0 -> - return Configuration.(Rolling, retention ~days ()) - | _ -> - failwith - "Invalid retention period %S for rolling history mode. Must be a \ - positive integer number of days." - n) - | _ -> + match Configuration.history_mode_of_string_opt s with + | Some mode -> return mode + | None -> failwith - "Invalid history mode. Must be either archive, rolling or rolling:n \ - where n is the number of days to retain history." + "Invalid history mode. Must be either archive, or rolling:n where n \ + is the number of days to retain history." let history next = Tezos_clic.param ~name:"history" ~desc: - "History mode, either archive, rolling or rolling:n where n is the \ - number of days of history to retain." + "History mode, either archive, or rolling:n where n is the number of \ + days of history to retain." history_param next end @@ -1701,7 +1691,7 @@ mode.|} evm_node_endpoint, threshold_encryption_bundler_endpoint, sequencer_sidecar_endpoint, - history, + history_mode, dont_track_rollup_node, wallet_dir, force, @@ -1719,11 +1709,6 @@ mode.|} Client_keys.Secret_key.parse_source_string wallet_ctxt str) sequencer_str in - let history_mode, garbage_collector_parameters = - match history with - | Some (hist_mode, gc_params) -> (Some hist_mode, Some gc_params) - | None -> (None, None) - in let* config = Cli.create_or_read_config ~data_dir @@ -1765,7 +1750,6 @@ mode.|} ~finalized_view ?network ?history_mode - ?garbage_collector_parameters () in let*! () = @@ -2434,7 +2418,15 @@ let snapshot_info_command = "@,History mode: %s@,First level: %a" (match history_mode with | Archive -> "Archive" - | Rolling -> "Rolling") + | Rolling gc -> + let hist_span = + Ptime.Span.of_int_s + (gc.split_frequency_in_seconds * gc.number_of_chunks) + in + Format.asprintf + "Rolling (with %a history)" + Ptime.Span.pp + hist_span) Evm_node_lib_dev_encoding.Ethereum_types.pp_quantity first_level in @@ -2462,7 +2454,7 @@ let switch_history_mode_command = ~desc:"Switch history mode of the node" (args1 data_dir_arg) (prefixes ["switch"; "history"; "to"] @@ Params.history @@ stop) - (fun data_dir (history_mode, garbage_collector_parameters) () -> + (fun data_dir history_mode () -> let open Lwt_result_syntax in let open Evm_node_lib_dev in let*! populated = Data_dir.populated ~data_dir in @@ -2476,13 +2468,7 @@ let switch_history_mode_command = let* store = Evm_store.init ~data_dir ~perm:`Read_write () in let* () = Evm_store.use store @@ fun conn -> - let* config = - Cli.create_or_read_config - ~data_dir - ~history_mode - ~garbage_collector_parameters - () - in + let* config = Cli.create_or_read_config ~data_dir ~history_mode () in let*! () = let open Tezos_base_unix.Internal_event_unix in let config = make_with_defaults ~verbosity:Warning () in @@ -2495,7 +2481,7 @@ let switch_history_mode_command = ~switch:true ~store_history_mode ~history_mode:config.history_mode - conn + () in let* () = Evm_store.Metadata.store_history_mode conn history_mode in let*! config_exists = diff --git a/etherlink/bin_node/migrations/018_rolling.sql b/etherlink/bin_node/migrations/018_rolling.sql new file mode 100644 index 0000000000000000000000000000000000000000..57d08e3a3d5b354cc0459253c6ac14e59ad52ca2 --- /dev/null +++ b/etherlink/bin_node/migrations/018_rolling.sql @@ -0,0 +1,4 @@ +-- rolling is no longer a valid value for history_mode +UPDATE metadata +SET value = 'rolling:14' +WHERE key = 'history_mode' AND value = 'rolling'; diff --git a/etherlink/script-inputs/evm_store_migrations b/etherlink/script-inputs/evm_store_migrations index a40c948d75abb20832d4b66aa7fbb0138466a7dd..91615717019f78901ee6e1513bdb436c4b830b7e 100644 --- a/etherlink/script-inputs/evm_store_migrations +++ b/etherlink/script-inputs/evm_store_migrations @@ -16,3 +16,4 @@ efd7da46af254996433066a6d2a6c692e60f7314130a5ba8ceee9e419e155118 etherlink/bin_ bd8fc14f18c1ca562e8b8e412a72bd36b071e28e84e8e8624b1f6581e70c144d etherlink/bin_node/migrations/015_irmin_chunks.sql 7c97ad4738c4c6672fd51e0357b5f4c4843ab1fb0a20e6925ca6a57879f339c6 etherlink/bin_node/migrations/016_history_mode.sql b223e97d75ca429e9130fcd37b3da7c8902b11c6177cec253949e25eeab32a8a etherlink/bin_node/migrations/017_legacy_mode.sql +a223d3797f36da6ea98e883cdb32734eaf5b1e20391c746adafbe46f146568aa etherlink/bin_node/migrations/018_rolling.sql diff --git a/etherlink/tezt/lib/evm_node.ml b/etherlink/tezt/lib/evm_node.ml index fe35a67fc0f3e9fdc16912208ead8c78eebc1fae..2271fdf5998201028d8acf739d1f2bb82a398a03 100644 --- a/etherlink/tezt/lib/evm_node.ml +++ b/etherlink/tezt/lib/evm_node.ml @@ -1275,12 +1275,7 @@ let patch_config_gc ?history_mode json = json |> optional_json_put ~name:"history" history_mode (function | Archive -> `String "archive" - | Rolling retention -> - `O - [ - ("mode", `String "rolling"); - ("retention", `Float (float_of_int retention)); - ]) + | Rolling retention -> `String (Format.sprintf "rolling:%d" retention)) let init ?patch_config ?name ?runner ?mode ?data_dir ?rpc_addr ?rpc_port ?restricted_rpcs ?history_mode rollup_node = diff --git a/etherlink/tezt/tests/expected/evm_rollup.ml/EVM node- list events regression.out b/etherlink/tezt/tests/expected/evm_rollup.ml/EVM node- list events regression.out index 95903ed42052d7453535710ee2e4f91f0df65ccb..27448ba47e2615ef33c6c895d9395ecbcbcafc87 100644 --- a/etherlink/tezt/tests/expected/evm_rollup.ml/EVM node- list events regression.out +++ b/etherlink/tezt/tests/expected/evm_rollup.ml/EVM node- list events regression.out @@ -507,8 +507,13 @@ evm_context_switch_history_mode: json format: { /* evm_context_switch_history_mode version 0 */ "evm_context_switch_history_mode.v0": - { "from": "rolling" | "archive", - "to_": "rolling" | "archive" } } + { "from": $history_mode, + "to_": $history_mode } } + $history_mode: + /* Compact notation for the history mode. Can either be `archive` and + `rolling:N` with `N` being the number of days to use as the + retention period */ + "archive" | "rolling:n" evm_context_rolling_to_archive_incomplete_history: description: switching history mode from Rolling to Archive, but be aware that history is incomplete, earliest level is {earliest_level} @@ -530,7 +535,12 @@ evm_context_start_history_mode: section: evm_node.dev.evm_context json format: { /* evm_context_start_history_mode version 0 */ - "evm_context_start_history_mode.v0": "rolling" | "archive" } + "evm_context_start_history_mode.v0": $history_mode } + $history_mode: + /* Compact notation for the history mode. Can either be `archive` and + `rolling:N` with `N` being the number of days to use as the + retention period */ + "archive" | "rolling:n" evm_context_get_block_failed: description: get block by number failed for level {level}{trace} diff --git a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- describe config.out b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- describe config.out index 8b24d3b7f5de5e03213251b01cbc9002cc4b68c8..f39a80427c61907c6d7fad4f3873317a3b51cf71 100644 --- a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- describe config.out +++ b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- describe config.out @@ -273,19 +273,12 @@ boolean /* When enabled, the node only expose blocks that are finalized, i.e., the `latest` block parameter becomes a synonym for `finalized`. */, - "history"?: - /* History mode of the EVM node */ - "archive" - || "rolling" - || { /* rolling */ - "mode": "rolling", - "retention": - $days - /* How much history is retained for rolling nodes. */ } } -$days: - /* number_of_days - Number of days of history to retain */ - integer ∈ [0, 2^30] + "history"?: $history_mode /* History mode of the EVM node */ } +$history_mode: + /* Compact notation for the history mode. Can either be `archive` and + `rolling:N` with `N` being the number of days to use as the retention + period */ + "archive" | "rolling:n" $int64: /* 64 bit integers Decimal representation of 64 bit integers */ diff --git a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out index 9fd64b9d8f49591da3e74249d4ff5e608cc18d91..9a4bac497ee2267b403688875c34d3e9365f3a0e 100644 --- a/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out +++ b/etherlink/tezt/tests/expected/evm_sequencer.ml/EVM Node- man.out @@ -260,7 +260,7 @@ Miscellaneous commands: switch history to [--data-dir ] Switch history mode of the node - : History mode, either archive, rolling or rolling:n where n is the number of days of history to retain. + : History mode, either archive, or rolling:n where n is the number of days of history to retain. --data-dir : The path to the EVM node data directory chunk data [...] [--rollup-address ] [--as-blueprint] diff --git a/etherlink/tezt/tests/gc.ml b/etherlink/tezt/tests/gc.ml index 3aea754e14e7e3721ded059b8891930206f07101..353783de704978dfa1746b2042c73e9998f098b6 100644 --- a/etherlink/tezt/tests/gc.ml +++ b/etherlink/tezt/tests/gc.ml @@ -20,7 +20,8 @@ open Rpc.Syntax -let register ?genesis_timestamp ?(retention_period = 5) ~title ~tags f = +let register ?genesis_timestamp ?(history_mode = Evm_node.Rolling 5) ~title + ~tags f = Test.register ~__FILE__ ~title @@ -39,7 +40,7 @@ let register ?genesis_timestamp ?(retention_period = 5) ~title ~tags f = let* sequencer = Helpers.init_sequencer_sandbox ?genesis_timestamp - ~history_mode:(Rolling retention_period) + ~history_mode ~patch_config () in @@ -52,7 +53,7 @@ let test_gc_boundaries () = let genesis_timestamp = Client.At genesis_time in register ~genesis_timestamp - ~retention_period:3 + ~history_mode:(Rolling 3) ~title:"GC boundaries" ~tags:["boundaries"; "earliest"] @@ fun sequencer -> @@ -124,49 +125,58 @@ let test_gc_boundaries () = let test_switch_history_mode () = let genesis_time = Client.Time.of_notation_exn "2020-01-01T00:00:00Z" in let genesis_timestamp = Client.At genesis_time in + let retention_period = 2 in + let get_timestamp i = + (* Move one day every block *) + Ptime.add_span genesis_time (days (i + 1)) + |> Option.get |> Client.Time.to_notation + in + let blocks_before_switch = 3 in register ~genesis_timestamp - ~retention_period:2 - ~title:"Switch history mode (rolling -> archive)" + ~title:"Switch history mode (archive -> rolling)" + ~history_mode:Archive ~tags:["history_mode"] @@ fun sequencer -> let* () = Evm_node.terminate sequencer in - let wait_for_rolling = - Evm_node.wait_for_start_history_mode ~history_mode:"rolling" sequencer + let wait_for_archive = + Evm_node.wait_for_start_history_mode ~history_mode:"archive" sequencer in - let* () = Evm_node.run sequencer and* _ = wait_for_rolling in - (* We want the evm-node to trigger at least one garbage collector to - have only partial history. *) - let wait_for_gc = Evm_node.wait_for_gc_finished sequencer in + let* () = Evm_node.run sequencer and* _ = wait_for_archive in let* _ = - fold 3 () (fun i () -> - let timestamp = - (* Move one day every block *) - Ptime.add_span genesis_time (days (i + 1)) - |> Option.get |> Client.Time.to_notation - in + fold blocks_before_switch () (fun i () -> + let timestamp = get_timestamp i in let* _ = Rpc.produce_block ~timestamp sequencer in unit) - and* _ = wait_for_gc in - let*@ earliest_block = Rpc.get_block_by_number ~block:"earliest" sequencer in - Check.((earliest_block.number > 0l) int32) - ~error_msg:"Garbage collector should have removed genesis block" ; + in (* Restart the node in archive mode. *) let* () = Evm_node.terminate sequencer in let* () = Evm_node.Config_file.update sequencer - (Evm_node.patch_config_gc ~history_mode:Archive) + (Evm_node.patch_config_gc ~history_mode:(Rolling retention_period)) in let process = Evm_node.spawn_run sequencer in let* () = Process.check_error ~msg:(rex "cannot be run with history mode") process in - let*! () = Evm_node.switch_history_mode sequencer Archive in - let wait_for_archive = - Evm_node.wait_for_start_history_mode ~history_mode:"archive" sequencer + let*! () = + Evm_node.switch_history_mode sequencer (Rolling retention_period) in - let* () = Evm_node.run sequencer and* _ = wait_for_archive in + let wait_for_rolling = + Evm_node.wait_for_start_history_mode + ~history_mode:(Format.sprintf "rolling:%d" retention_period) + sequencer + in + let* () = Evm_node.run sequencer and* _ = wait_for_rolling in + (* show that we indeed gc *) + let wait_for_gc = Evm_node.wait_for_gc_finished sequencer in + let* _ = + fold (retention_period + 1) () (fun i () -> + let timestamp = get_timestamp (blocks_before_switch + i + 1) in + let* _ = Rpc.produce_block ~timestamp sequencer in + unit) + and* _ = wait_for_gc in unit let () =