From 77d4f4c4583c30667b1705301bfe8cc6a5be911f Mon Sep 17 00:00:00 2001 From: Alain Mebsout Date: Tue, 23 Jul 2024 17:12:16 +0200 Subject: [PATCH] Evm node: export evm context in snapshot file --- etherlink/bin_node/lib_dev/evm_context.ml | 2 + etherlink/bin_node/lib_dev/evm_context.mli | 8 ++ etherlink/bin_node/lib_dev/snapshots.ml | 109 +++++++++++++++++++++ etherlink/bin_node/lib_dev/snapshots.mli | 43 ++++++++ 4 files changed, 162 insertions(+) create mode 100644 etherlink/bin_node/lib_dev/snapshots.ml create mode 100644 etherlink/bin_node/lib_dev/snapshots.mli diff --git a/etherlink/bin_node/lib_dev/evm_context.ml b/etherlink/bin_node/lib_dev/evm_context.ml index 36899ed2c590..e33b1f03c37c 100644 --- a/etherlink/bin_node/lib_dev/evm_context.ml +++ b/etherlink/bin_node/lib_dev/evm_context.ml @@ -330,6 +330,8 @@ module State = struct Evm_store.use ctxt.store @@ fun conn -> Evm_store.with_transaction conn @@ fun conn -> k conn + let store_path ~data_dir = Filename.Infix.(data_dir // "store") + let lockfile_path ~store_path = Filename.Infix.(store_path // "evm_lock") let load ~data_dir ~store_perm:perm index = diff --git a/etherlink/bin_node/lib_dev/evm_context.mli b/etherlink/bin_node/lib_dev/evm_context.mli index c78ab8be6284..61f5fcf635b7 100644 --- a/etherlink/bin_node/lib_dev/evm_context.mli +++ b/etherlink/bin_node/lib_dev/evm_context.mli @@ -174,3 +174,11 @@ val execute : Simulation.Encodings.simulate_input -> Ethereum_types.Block_parameter.extended -> Irmin_context.tree tzresult Lwt.t + +module State : sig + (** Path of EVM state store. *) + val store_path : data_dir:string -> string + + (** Path of lock file for EVM state w.r.t. {!store_path}. *) + val lockfile_path : store_path:string -> string +end diff --git a/etherlink/bin_node/lib_dev/snapshots.ml b/etherlink/bin_node/lib_dev/snapshots.ml new file mode 100644 index 000000000000..3a5175c1d8df --- /dev/null +++ b/etherlink/bin_node/lib_dev/snapshots.ml @@ -0,0 +1,109 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Functori *) +(* *) +(*****************************************************************************) + +open Snapshot_utils + +module Event = struct + open Internal_event.Simple + + let section = ["evm_node"; "snapshot"] + + let take_evm_stats_lock = + declare_0 + ~section + ~name:"evm_stats_lock" + ~msg:"Acquiring EVM state lock" + ~level:Info + () + + let emit_evm_stats_lock = emit take_evm_stats_lock +end + +type compression = No | On_the_fly | After + +module Header = struct + type version = V0 + + (* TODO: https://gitlab.com/tezos/tezos/-/issues/7433 + header with more information. *) + type t = {version : version} + + let encoding = + let open Data_encoding in + union + [ + case + ~title:"evm_node.snapshot_header.v0" + (Tag 0) + Data_encoding.unit + (fun {version = V0} -> Some ()) + (fun () -> {version = V0}); + ] + + let size = + Data_encoding.Binary.fixed_length encoding + |> WithExceptions.Option.get ~loc:__LOC__ +end + +open Snapshot_utils.Make (Header) + +let export ?dest ?filename ~compression ~data_dir () = + let open Lwt_result_syntax in + let header = Header.{version = V0} in + let dest_file_name = + match filename with + | Some f -> f + | None -> + let suffix = + match compression with + | On_the_fly -> ".compressed" + | No | After -> ".uncompressed" + in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/7433 + name based on header *) + Format.asprintf "evm-snapshot%s" suffix + in + let dest_file = + match dest with + | Some dest -> Filename.concat dest dest_file_name + | None -> dest_file_name + in + let*! () = Lwt_utils_unix.create_dir (Filename.dirname dest_file) in + let evm_state_path = Evm_context.State.store_path ~data_dir in + let lockfile_name = + Evm_context.State.lockfile_path ~store_path:evm_state_path + in + let* () = + let*! () = Event.emit_evm_stats_lock () in + Lwt_lock_file.with_lock ~when_locked:`Block ~filename:lockfile_name + @@ fun () -> + let evm_context_files = + Tezos_stdlib_unix.Utils.fold_files + evm_state_path + (fun relative_path acc -> + let full_path = Filename.concat evm_state_path relative_path in + if full_path = lockfile_name then acc + else (full_path, Filename.concat "store" relative_path) :: acc) + [] + in + let files = evm_context_files in + (* TODO: add store.sql *) + (* TODO: add wasm_2_0_0 *) + let writer = + match compression with + | On_the_fly -> gzip_writer + | No | After -> stdlib_writer + in + create stdlib_reader writer header ~files ~dest:dest_file ; + return_unit + in + let snapshot_file = + match compression with + | No | On_the_fly -> dest_file + | After -> compress ~snapshot_file:dest_file + in + return snapshot_file diff --git a/etherlink/bin_node/lib_dev/snapshots.mli b/etherlink/bin_node/lib_dev/snapshots.mli new file mode 100644 index 000000000000..02bd31ccb7c7 --- /dev/null +++ b/etherlink/bin_node/lib_dev/snapshots.mli @@ -0,0 +1,43 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* Copyright (c) 2024 Functori *) +(* *) +(*****************************************************************************) + +(** Compression strategy for snapshot archives. *) +type compression = + | No (** Produce uncompressed archive. Takes more space. *) + | On_the_fly + (** Compress archive on the fly. The rollup node will use less disk space + to produce the snapshot but will lock the rollup node (if running) for + a longer time. *) + | After + (** Compress archive after snapshot creation. Uses more disk space + temporarily than {!On_the_fly} but does not lock the rollup node for + very long. *) + +module Header : sig + (** Versioning of snapshot format. Only one version for now. *) + type version = V0 + + (** Snapshot metadata for version 0. This information is written as a header of + the archive snapshot file. *) + type t = {version : version} + + (** Fixed size metadata encoding. *) + val encoding : t Data_encoding.t +end + +(** [export ?dest ?filename ~compression ~data_dir () ] creates a + tar gzipped archive with name [filename] (or a generated name) in [dest] (or + the current directory) containing a snapshot of the data of the rollup node + with data directory [data_dir]. The path of the snapshot archive is + returned. *) +val export : + ?dest:string -> + ?filename:string -> + compression:compression -> + data_dir:string -> + unit -> + string tzresult Lwt.t -- GitLab