diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/context.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/context.ml index cb60df692018af8ae94a4f9eb4b4e69b540f2a8f..afbce3ba94818b3f4dc36bbec434bf1691937479 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/context.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/context.ml @@ -204,7 +204,7 @@ end module Rollup = struct let path = ["rollup_address"] - let set_address (index : _ index) addr = + let set_address (index : rw_index) addr = let open Lwt_result_syntax in protect @@ fun () -> let info () = @@ -220,7 +220,7 @@ module Rollup = struct let*! () = IStore.set_exn ~info store path value in return_unit - let get_address (index : _ index) = + let get_address (index : _ raw_index) = let open Lwt_result_syntax in protect @@ fun () -> let*! store = IStore.main index.repo in @@ -229,4 +229,80 @@ module Rollup = struct @@ Option.map (Data_encoding.Binary.of_bytes_exn Sc_rollup.Address.encoding) value + + let check_or_set_address (type a) (mode : a mode) (index : a raw_index) + rollup_address = + let open Lwt_result_syntax in + let* saved_address = get_address index in + match saved_address with + | Some saved_address -> + fail_unless Sc_rollup.Address.(rollup_address = saved_address) + @@ Sc_rollup_node_errors.Unexpected_rollup + {rollup_address; saved_address} + | None -> ( + (* Address was never saved, we set it permanently if not in read-only + mode. *) + match mode with + | Store_sigs.Read_only -> return_unit + | Read_write -> set_address index rollup_address) end + +module Version = struct + type t = V0 + + let version = V0 + + let encoding = + let open Data_encoding in + conv + (fun V0 -> 0) + (function + | 0 -> V0 + | v -> + Format.ksprintf Stdlib.failwith "Unsupported context version %d" v) + int31 + + let path = ["context_version"] + + let set (index : rw_index) = + let open Lwt_result_syntax in + protect @@ fun () -> + let info () = + let date = + Time.(System.now () |> System.to_protocol |> Protocol.to_seconds) + in + IStore.Info.v date + in + let value = Data_encoding.Binary.to_bytes_exn encoding version in + let*! store = IStore.main index.repo in + let*! () = IStore.set_exn ~info store path value in + return_unit + + let get (index : _ index) = + let open Lwt_result_syntax in + protect @@ fun () -> + let*! store = IStore.main index.repo in + let*! value = IStore.find store path in + return @@ Option.map (Data_encoding.Binary.of_bytes_exn encoding) value + + let check (index : _ index) = + let open Lwt_result_syntax in + let* context_version = get index in + match context_version with None | Some V0 -> return_unit + + let check_and_set (index : _ index) = + let open Lwt_result_syntax in + let* context_version = get index in + match context_version with None -> set index | Some V0 -> return_unit +end + +let load : type a. a mode -> string -> a raw_index tzresult Lwt.t = + fun mode path -> + let open Lwt_result_syntax in + let*! index = load mode path in + let+ () = + match mode with + | Read_only -> Version.check index + | Read_write -> Version.check_and_set index + in + index diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/context.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/context.mli index 636bb700d1d94d4e7ef9910983e03509cd110229..d4c1acbc98e5efdf05363c768ca88dbe06deac54 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/context.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/context.mli @@ -55,7 +55,7 @@ type hash = Sc_rollup_context_hash.t type commit (** [load path] initializes from disk a context from [path]. *) -val load : 'a mode -> string -> 'a index Lwt.t +val load : 'a mode -> string -> 'a index tzresult Lwt.t (** [index context] is the repository of the context [context]. *) val index : 'a t -> 'a index @@ -162,9 +162,12 @@ end (** Static information about the rollup. *) module Rollup : sig - val set_address : - _ index -> Protocol.Alpha_context.Sc_rollup.Address.t -> unit tzresult Lwt.t - val get_address : _ index -> Protocol.Alpha_context.Sc_rollup.Address.t option tzresult Lwt.t + + val check_or_set_address : + 'a mode -> + 'a index -> + Protocol.Alpha_context.Sc_rollup.Address.t -> + unit tzresult Lwt.t end 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 576c7b9c182a62b96d9cba314295fed02e8c9b08..9d563d818b69613946a29ae82040c534b35fcf34 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 @@ -133,17 +133,6 @@ let get_last_published_commitment (cctxt : Protocol_client_context.full) | Ok None -> return_none | Ok (Some (_staked_hash, staked_commitment)) -> return_some staked_commitment -let check_and_set_rollup_address context rollup_address = - let open Lwt_result_syntax in - let* saved_address = Context.Rollup.get_address context in - match saved_address with - | None -> - (* Address was never saved, we set it permanently. *) - Context.Rollup.set_address context rollup_address - | Some saved_address -> - fail_unless Sc_rollup.Address.(rollup_address = saved_address) - @@ Sc_rollup_node_errors.Unexpected_rollup {rollup_address; saved_address} - let lock ~data_dir = let lockfile_path = Filename.concat data_dir "lock" in let lock_aux ~data_dir = @@ -316,10 +305,10 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file ~l2_blocks_cache_size Configuration.(default_storage_dir data_dir) in - let*! context = + let* context = Context.load mode (Configuration.default_context_dir data_dir) in - let* () = check_and_set_rollup_address context rollup_address in + let* () = Context.Rollup.check_or_set_address mode context rollup_address in let* l1_ctxt = Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt in @@ -966,7 +955,7 @@ module Internal_for_tests = struct ~l2_blocks_cache_size Configuration.(default_storage_dir data_dir) in - let*! context = + let* context = Context.load Read_write (Configuration.default_context_dir data_dir) in let genesis_info = diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/store_migration.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/store_migration.ml index 5e3c45dc772bfafac988af2d901687fd2ee8cf97..2c3fd7901eca6c2b8475346f51737f314f14ecf7 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/store_migration.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/store_migration.ml @@ -25,11 +25,13 @@ open Store_version +type version_result = Version_known | Unintialized_version + let messages_store_location ~storage_dir = let open Filename.Infix in storage_dir // "messages" -let version_of_unversionned_store ~storage_dir = +let version_of_unversioned_store ~storage_dir = let open Lwt_syntax in let path = messages_store_location ~storage_dir in let* messages_store_v0 = Store_v0.Messages.load ~path ~cache_size:1 Read_only @@ -59,14 +61,18 @@ let version_of_unversionned_store ~storage_dir = return_none | Error _, Error _ -> failwith - "Cannot determine unversionned store version (no messages decodable)" + "Cannot determine unversioned store version (no messages decodable)" in Lwt.finalize guess_version cleanup let version_of_store ~storage_dir = - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5554 - Use store version information when available. *) - version_of_unversionned_store ~storage_dir + let open Lwt_result_syntax in + let* version = Store_version.read_version_file ~dir:storage_dir in + match version with + | Some v -> return_some (v, Version_known) + | None -> + let+ v = version_of_unversioned_store ~storage_dir in + Option.map (fun v -> (v, Unintialized_version)) v module type MIGRATION_ACTIONS = sig type from_store @@ -143,7 +149,7 @@ module Make Actions.final_actions ~storage_dir ~tmp_dir source_store dest_store in let*! () = Lwt_utils_unix.remove_dir tmp_dir in - return_unit + Store_version.write_version_file ~dir:storage_dir S_dest.version in Lwt.finalize run_migration cleanup @@ -182,12 +188,16 @@ let maybe_run_migration ~storage_dir = let last_version = Store.version in match (current_version, last_version) with | None, _ -> - (* Store not initialized, nothing to do *) - return_unit - | Some current, last when last = current -> - (* Up to date, nothing to do *) - return_unit - | Some current, last -> ( + (* Store not initialized, write last version *) + Store_version.write_version_file ~dir:storage_dir last_version + | Some (current, versioned), last when last = current -> ( + match versioned with + | Unintialized_version -> + Store_version.write_version_file ~dir:storage_dir last_version + | Version_known -> + (* Up to date, nothing to do *) + return_unit) + | Some (current, _), last -> ( let migrations = migration_path ~from:current ~dest:last in match migrations with | None -> diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/store_version.ml b/src/proto_016_PtMumbai/lib_sc_rollup_node/store_version.ml index ec294eb1a23f97d620a16c84aca2307a7d0ba21d..cdb8252b3bae35556ae7b323e08b33118bb870e1 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/store_version.ml +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/store_version.ml @@ -27,3 +27,33 @@ type t = V0 | V1 let pp ppf v = Format.pp_print_string ppf @@ match v with V0 -> "v0" | V1 -> "v1" + +let encoding = + let open Data_encoding in + conv + (function V0 -> 0 | V1 -> 1) + (function + | 0 -> V0 + | 1 -> V1 + | v -> Format.ksprintf Stdlib.failwith "Unsupported store version %d" v) + (obj1 (req "store_version" int31)) + +let path ~dir = Filename.concat dir "version" + +let read_version_file ~dir = + let open Lwt_result_syntax in + protect @@ fun () -> + let filename = path ~dir in + let*! exists = Lwt_unix.file_exists filename in + if not exists then return_none + else + let* json = Lwt_utils_unix.Json.read_file filename in + return_some (Data_encoding.Json.destruct encoding json) + +let write_version_file ~dir version = + let open Lwt_result_syntax in + protect @@ fun () -> + let filename = path ~dir in + let*! () = Lwt_utils_unix.create_dir dir in + let json = Data_encoding.Json.construct encoding version in + Lwt_utils_unix.Json.write_file filename json diff --git a/src/proto_016_PtMumbai/lib_sc_rollup_node/store_version.mli b/src/proto_016_PtMumbai/lib_sc_rollup_node/store_version.mli index 86b8485e19c100a8cf59be262e443f1e684767c5..870c76d05ba28a4e2039bdfa9b4e1db939aaa694 100644 --- a/src/proto_016_PtMumbai/lib_sc_rollup_node/store_version.mli +++ b/src/proto_016_PtMumbai/lib_sc_rollup_node/store_version.mli @@ -27,3 +27,9 @@ type t = V0 | V1 (** Pretty-printer for store versions *) val pp : Format.formatter -> t -> unit + +(** Read the version file from [dir]. *) +val read_version_file : dir:string -> t option tzresult Lwt.t + +(** Write a version to the version file in [dir]. *) +val write_version_file : dir:string -> t -> unit tzresult Lwt.t diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/context.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/context.ml index cb60df692018af8ae94a4f9eb4b4e69b540f2a8f..afbce3ba94818b3f4dc36bbec434bf1691937479 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/context.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/context.ml @@ -204,7 +204,7 @@ end module Rollup = struct let path = ["rollup_address"] - let set_address (index : _ index) addr = + let set_address (index : rw_index) addr = let open Lwt_result_syntax in protect @@ fun () -> let info () = @@ -220,7 +220,7 @@ module Rollup = struct let*! () = IStore.set_exn ~info store path value in return_unit - let get_address (index : _ index) = + let get_address (index : _ raw_index) = let open Lwt_result_syntax in protect @@ fun () -> let*! store = IStore.main index.repo in @@ -229,4 +229,80 @@ module Rollup = struct @@ Option.map (Data_encoding.Binary.of_bytes_exn Sc_rollup.Address.encoding) value + + let check_or_set_address (type a) (mode : a mode) (index : a raw_index) + rollup_address = + let open Lwt_result_syntax in + let* saved_address = get_address index in + match saved_address with + | Some saved_address -> + fail_unless Sc_rollup.Address.(rollup_address = saved_address) + @@ Sc_rollup_node_errors.Unexpected_rollup + {rollup_address; saved_address} + | None -> ( + (* Address was never saved, we set it permanently if not in read-only + mode. *) + match mode with + | Store_sigs.Read_only -> return_unit + | Read_write -> set_address index rollup_address) end + +module Version = struct + type t = V0 + + let version = V0 + + let encoding = + let open Data_encoding in + conv + (fun V0 -> 0) + (function + | 0 -> V0 + | v -> + Format.ksprintf Stdlib.failwith "Unsupported context version %d" v) + int31 + + let path = ["context_version"] + + let set (index : rw_index) = + let open Lwt_result_syntax in + protect @@ fun () -> + let info () = + let date = + Time.(System.now () |> System.to_protocol |> Protocol.to_seconds) + in + IStore.Info.v date + in + let value = Data_encoding.Binary.to_bytes_exn encoding version in + let*! store = IStore.main index.repo in + let*! () = IStore.set_exn ~info store path value in + return_unit + + let get (index : _ index) = + let open Lwt_result_syntax in + protect @@ fun () -> + let*! store = IStore.main index.repo in + let*! value = IStore.find store path in + return @@ Option.map (Data_encoding.Binary.of_bytes_exn encoding) value + + let check (index : _ index) = + let open Lwt_result_syntax in + let* context_version = get index in + match context_version with None | Some V0 -> return_unit + + let check_and_set (index : _ index) = + let open Lwt_result_syntax in + let* context_version = get index in + match context_version with None -> set index | Some V0 -> return_unit +end + +let load : type a. a mode -> string -> a raw_index tzresult Lwt.t = + fun mode path -> + let open Lwt_result_syntax in + let*! index = load mode path in + let+ () = + match mode with + | Read_only -> Version.check index + | Read_write -> Version.check_and_set index + in + index diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/context.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/context.mli index 636bb700d1d94d4e7ef9910983e03509cd110229..d4c1acbc98e5efdf05363c768ca88dbe06deac54 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/context.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/context.mli @@ -55,7 +55,7 @@ type hash = Sc_rollup_context_hash.t type commit (** [load path] initializes from disk a context from [path]. *) -val load : 'a mode -> string -> 'a index Lwt.t +val load : 'a mode -> string -> 'a index tzresult Lwt.t (** [index context] is the repository of the context [context]. *) val index : 'a t -> 'a index @@ -162,9 +162,12 @@ end (** Static information about the rollup. *) module Rollup : sig - val set_address : - _ index -> Protocol.Alpha_context.Sc_rollup.Address.t -> unit tzresult Lwt.t - val get_address : _ index -> Protocol.Alpha_context.Sc_rollup.Address.t option tzresult Lwt.t + + val check_or_set_address : + 'a mode -> + 'a index -> + Protocol.Alpha_context.Sc_rollup.Address.t -> + unit tzresult Lwt.t end 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 017d28c07b1f8b473205025798cdf260f3df7702..9739dc6477ad71a77e334e7da45d06844b0da148 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 @@ -133,17 +133,6 @@ let get_last_published_commitment (cctxt : Protocol_client_context.full) | Ok None -> return_none | Ok (Some (_staked_hash, staked_commitment)) -> return_some staked_commitment -let check_and_set_rollup_address context rollup_address = - let open Lwt_result_syntax in - let* saved_address = Context.Rollup.get_address context in - match saved_address with - | None -> - (* Address was never saved, we set it permanently. *) - Context.Rollup.set_address context rollup_address - | Some saved_address -> - fail_unless Sc_rollup.Address.(rollup_address = saved_address) - @@ Sc_rollup_node_errors.Unexpected_rollup {rollup_address; saved_address} - let lock ~data_dir = let lockfile_path = Filename.concat data_dir "lock" in let lock_aux ~data_dir = @@ -316,10 +305,10 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file ~l2_blocks_cache_size Configuration.(default_storage_dir data_dir) in - let*! context = + let* context = Context.load mode (Configuration.default_context_dir data_dir) in - let* () = check_and_set_rollup_address context rollup_address in + let* () = Context.Rollup.check_or_set_address mode context rollup_address in let* l1_ctxt = Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt in @@ -937,7 +926,7 @@ module Internal_for_tests = struct ~l2_blocks_cache_size Configuration.(default_storage_dir data_dir) in - let*! context = + let* context = Context.load Read_write (Configuration.default_context_dir data_dir) in let genesis_info = diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/store_migration.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/store_migration.ml index 5e3c45dc772bfafac988af2d901687fd2ee8cf97..2c3fd7901eca6c2b8475346f51737f314f14ecf7 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/store_migration.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/store_migration.ml @@ -25,11 +25,13 @@ open Store_version +type version_result = Version_known | Unintialized_version + let messages_store_location ~storage_dir = let open Filename.Infix in storage_dir // "messages" -let version_of_unversionned_store ~storage_dir = +let version_of_unversioned_store ~storage_dir = let open Lwt_syntax in let path = messages_store_location ~storage_dir in let* messages_store_v0 = Store_v0.Messages.load ~path ~cache_size:1 Read_only @@ -59,14 +61,18 @@ let version_of_unversionned_store ~storage_dir = return_none | Error _, Error _ -> failwith - "Cannot determine unversionned store version (no messages decodable)" + "Cannot determine unversioned store version (no messages decodable)" in Lwt.finalize guess_version cleanup let version_of_store ~storage_dir = - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5554 - Use store version information when available. *) - version_of_unversionned_store ~storage_dir + let open Lwt_result_syntax in + let* version = Store_version.read_version_file ~dir:storage_dir in + match version with + | Some v -> return_some (v, Version_known) + | None -> + let+ v = version_of_unversioned_store ~storage_dir in + Option.map (fun v -> (v, Unintialized_version)) v module type MIGRATION_ACTIONS = sig type from_store @@ -143,7 +149,7 @@ module Make Actions.final_actions ~storage_dir ~tmp_dir source_store dest_store in let*! () = Lwt_utils_unix.remove_dir tmp_dir in - return_unit + Store_version.write_version_file ~dir:storage_dir S_dest.version in Lwt.finalize run_migration cleanup @@ -182,12 +188,16 @@ let maybe_run_migration ~storage_dir = let last_version = Store.version in match (current_version, last_version) with | None, _ -> - (* Store not initialized, nothing to do *) - return_unit - | Some current, last when last = current -> - (* Up to date, nothing to do *) - return_unit - | Some current, last -> ( + (* Store not initialized, write last version *) + Store_version.write_version_file ~dir:storage_dir last_version + | Some (current, versioned), last when last = current -> ( + match versioned with + | Unintialized_version -> + Store_version.write_version_file ~dir:storage_dir last_version + | Version_known -> + (* Up to date, nothing to do *) + return_unit) + | Some (current, _), last -> ( let migrations = migration_path ~from:current ~dest:last in match migrations with | None -> diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/store_version.ml b/src/proto_017_PtNairob/lib_sc_rollup_node/store_version.ml index ec294eb1a23f97d620a16c84aca2307a7d0ba21d..cdb8252b3bae35556ae7b323e08b33118bb870e1 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/store_version.ml +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/store_version.ml @@ -27,3 +27,33 @@ type t = V0 | V1 let pp ppf v = Format.pp_print_string ppf @@ match v with V0 -> "v0" | V1 -> "v1" + +let encoding = + let open Data_encoding in + conv + (function V0 -> 0 | V1 -> 1) + (function + | 0 -> V0 + | 1 -> V1 + | v -> Format.ksprintf Stdlib.failwith "Unsupported store version %d" v) + (obj1 (req "store_version" int31)) + +let path ~dir = Filename.concat dir "version" + +let read_version_file ~dir = + let open Lwt_result_syntax in + protect @@ fun () -> + let filename = path ~dir in + let*! exists = Lwt_unix.file_exists filename in + if not exists then return_none + else + let* json = Lwt_utils_unix.Json.read_file filename in + return_some (Data_encoding.Json.destruct encoding json) + +let write_version_file ~dir version = + let open Lwt_result_syntax in + protect @@ fun () -> + let filename = path ~dir in + let*! () = Lwt_utils_unix.create_dir dir in + let json = Data_encoding.Json.construct encoding version in + Lwt_utils_unix.Json.write_file filename json diff --git a/src/proto_017_PtNairob/lib_sc_rollup_node/store_version.mli b/src/proto_017_PtNairob/lib_sc_rollup_node/store_version.mli index 86b8485e19c100a8cf59be262e443f1e684767c5..870c76d05ba28a4e2039bdfa9b4e1db939aaa694 100644 --- a/src/proto_017_PtNairob/lib_sc_rollup_node/store_version.mli +++ b/src/proto_017_PtNairob/lib_sc_rollup_node/store_version.mli @@ -27,3 +27,9 @@ type t = V0 | V1 (** Pretty-printer for store versions *) val pp : Format.formatter -> t -> unit + +(** Read the version file from [dir]. *) +val read_version_file : dir:string -> t option tzresult Lwt.t + +(** Write a version to the version file in [dir]. *) +val write_version_file : dir:string -> t -> unit tzresult Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/context.ml b/src/proto_alpha/lib_sc_rollup_node/context.ml index cb60df692018af8ae94a4f9eb4b4e69b540f2a8f..afbce3ba94818b3f4dc36bbec434bf1691937479 100644 --- a/src/proto_alpha/lib_sc_rollup_node/context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/context.ml @@ -204,7 +204,7 @@ end module Rollup = struct let path = ["rollup_address"] - let set_address (index : _ index) addr = + let set_address (index : rw_index) addr = let open Lwt_result_syntax in protect @@ fun () -> let info () = @@ -220,7 +220,7 @@ module Rollup = struct let*! () = IStore.set_exn ~info store path value in return_unit - let get_address (index : _ index) = + let get_address (index : _ raw_index) = let open Lwt_result_syntax in protect @@ fun () -> let*! store = IStore.main index.repo in @@ -229,4 +229,80 @@ module Rollup = struct @@ Option.map (Data_encoding.Binary.of_bytes_exn Sc_rollup.Address.encoding) value + + let check_or_set_address (type a) (mode : a mode) (index : a raw_index) + rollup_address = + let open Lwt_result_syntax in + let* saved_address = get_address index in + match saved_address with + | Some saved_address -> + fail_unless Sc_rollup.Address.(rollup_address = saved_address) + @@ Sc_rollup_node_errors.Unexpected_rollup + {rollup_address; saved_address} + | None -> ( + (* Address was never saved, we set it permanently if not in read-only + mode. *) + match mode with + | Store_sigs.Read_only -> return_unit + | Read_write -> set_address index rollup_address) end + +module Version = struct + type t = V0 + + let version = V0 + + let encoding = + let open Data_encoding in + conv + (fun V0 -> 0) + (function + | 0 -> V0 + | v -> + Format.ksprintf Stdlib.failwith "Unsupported context version %d" v) + int31 + + let path = ["context_version"] + + let set (index : rw_index) = + let open Lwt_result_syntax in + protect @@ fun () -> + let info () = + let date = + Time.(System.now () |> System.to_protocol |> Protocol.to_seconds) + in + IStore.Info.v date + in + let value = Data_encoding.Binary.to_bytes_exn encoding version in + let*! store = IStore.main index.repo in + let*! () = IStore.set_exn ~info store path value in + return_unit + + let get (index : _ index) = + let open Lwt_result_syntax in + protect @@ fun () -> + let*! store = IStore.main index.repo in + let*! value = IStore.find store path in + return @@ Option.map (Data_encoding.Binary.of_bytes_exn encoding) value + + let check (index : _ index) = + let open Lwt_result_syntax in + let* context_version = get index in + match context_version with None | Some V0 -> return_unit + + let check_and_set (index : _ index) = + let open Lwt_result_syntax in + let* context_version = get index in + match context_version with None -> set index | Some V0 -> return_unit +end + +let load : type a. a mode -> string -> a raw_index tzresult Lwt.t = + fun mode path -> + let open Lwt_result_syntax in + let*! index = load mode path in + let+ () = + match mode with + | Read_only -> Version.check index + | Read_write -> Version.check_and_set index + in + index diff --git a/src/proto_alpha/lib_sc_rollup_node/context.mli b/src/proto_alpha/lib_sc_rollup_node/context.mli index 1a54302fd851d81dc8c12dda2a7f195f34d0621a..6a2f40660c1200aa296c9635c218032388586d34 100644 --- a/src/proto_alpha/lib_sc_rollup_node/context.mli +++ b/src/proto_alpha/lib_sc_rollup_node/context.mli @@ -55,7 +55,7 @@ type hash = Sc_rollup_context_hash.t type commit (** [load path] initializes from disk a context from [path]. *) -val load : 'a mode -> string -> 'a index Lwt.t +val load : 'a mode -> string -> 'a index tzresult Lwt.t (** [index context] is the repository of the context [context]. *) val index : 'a t -> 'a index @@ -162,9 +162,12 @@ end (** Static information about the rollup. *) module Rollup : sig - val set_address : - _ index -> Protocol.Alpha_context.Sc_rollup.Address.t -> unit tzresult Lwt.t - val get_address : _ index -> Protocol.Alpha_context.Sc_rollup.Address.t option tzresult Lwt.t + + val check_or_set_address : + 'a mode -> + 'a index -> + Protocol.Alpha_context.Sc_rollup.Address.t -> + unit tzresult Lwt.t end 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 f3d0be249b2df6fab092cef84e71264859014a50..3eee7f9296693948eb84f01ee0d8ffdfdd0f8c98 100644 --- a/src/proto_alpha/lib_sc_rollup_node/node_context.ml +++ b/src/proto_alpha/lib_sc_rollup_node/node_context.ml @@ -124,17 +124,6 @@ let get_last_published_commitment (cctxt : Protocol_client_context.full) | Ok None -> return_none | Ok (Some (_staked_hash, staked_commitment)) -> return_some staked_commitment -let check_and_set_rollup_address context rollup_address = - let open Lwt_result_syntax in - let* saved_address = Context.Rollup.get_address context in - match saved_address with - | None -> - (* Address was never saved, we set it permanently. *) - Context.Rollup.set_address context rollup_address - | Some saved_address -> - fail_unless Sc_rollup.Address.(rollup_address = saved_address) - @@ Sc_rollup_node_errors.Unexpected_rollup {rollup_address; saved_address} - let lock ~data_dir = let lockfile_path = Filename.concat data_dir "lock" in let lock_aux ~data_dir = @@ -303,10 +292,10 @@ let init (cctxt : Protocol_client_context.full) ~data_dir ?log_kernel_debug_file ~l2_blocks_cache_size Configuration.(default_storage_dir data_dir) in - let*! context = + let* context = Context.load mode (Configuration.default_context_dir data_dir) in - let* () = check_and_set_rollup_address context rollup_address in + let* () = Context.Rollup.check_or_set_address mode context rollup_address in let* l1_ctxt = Layer1.start ~name:"sc_rollup_node" ~reconnection_delay cctxt in @@ -940,7 +929,7 @@ module Internal_for_tests = struct ~l2_blocks_cache_size Configuration.(default_storage_dir data_dir) in - let*! context = + let* context = Context.load Read_write (Configuration.default_context_dir data_dir) in let genesis_info = diff --git a/src/proto_alpha/lib_sc_rollup_node/store_migration.ml b/src/proto_alpha/lib_sc_rollup_node/store_migration.ml index 5e3c45dc772bfafac988af2d901687fd2ee8cf97..2c3fd7901eca6c2b8475346f51737f314f14ecf7 100644 --- a/src/proto_alpha/lib_sc_rollup_node/store_migration.ml +++ b/src/proto_alpha/lib_sc_rollup_node/store_migration.ml @@ -25,11 +25,13 @@ open Store_version +type version_result = Version_known | Unintialized_version + let messages_store_location ~storage_dir = let open Filename.Infix in storage_dir // "messages" -let version_of_unversionned_store ~storage_dir = +let version_of_unversioned_store ~storage_dir = let open Lwt_syntax in let path = messages_store_location ~storage_dir in let* messages_store_v0 = Store_v0.Messages.load ~path ~cache_size:1 Read_only @@ -59,14 +61,18 @@ let version_of_unversionned_store ~storage_dir = return_none | Error _, Error _ -> failwith - "Cannot determine unversionned store version (no messages decodable)" + "Cannot determine unversioned store version (no messages decodable)" in Lwt.finalize guess_version cleanup let version_of_store ~storage_dir = - (* TODO: https://gitlab.com/tezos/tezos/-/issues/5554 - Use store version information when available. *) - version_of_unversionned_store ~storage_dir + let open Lwt_result_syntax in + let* version = Store_version.read_version_file ~dir:storage_dir in + match version with + | Some v -> return_some (v, Version_known) + | None -> + let+ v = version_of_unversioned_store ~storage_dir in + Option.map (fun v -> (v, Unintialized_version)) v module type MIGRATION_ACTIONS = sig type from_store @@ -143,7 +149,7 @@ module Make Actions.final_actions ~storage_dir ~tmp_dir source_store dest_store in let*! () = Lwt_utils_unix.remove_dir tmp_dir in - return_unit + Store_version.write_version_file ~dir:storage_dir S_dest.version in Lwt.finalize run_migration cleanup @@ -182,12 +188,16 @@ let maybe_run_migration ~storage_dir = let last_version = Store.version in match (current_version, last_version) with | None, _ -> - (* Store not initialized, nothing to do *) - return_unit - | Some current, last when last = current -> - (* Up to date, nothing to do *) - return_unit - | Some current, last -> ( + (* Store not initialized, write last version *) + Store_version.write_version_file ~dir:storage_dir last_version + | Some (current, versioned), last when last = current -> ( + match versioned with + | Unintialized_version -> + Store_version.write_version_file ~dir:storage_dir last_version + | Version_known -> + (* Up to date, nothing to do *) + return_unit) + | Some (current, _), last -> ( let migrations = migration_path ~from:current ~dest:last in match migrations with | None -> diff --git a/src/proto_alpha/lib_sc_rollup_node/store_version.ml b/src/proto_alpha/lib_sc_rollup_node/store_version.ml index ec294eb1a23f97d620a16c84aca2307a7d0ba21d..cdb8252b3bae35556ae7b323e08b33118bb870e1 100644 --- a/src/proto_alpha/lib_sc_rollup_node/store_version.ml +++ b/src/proto_alpha/lib_sc_rollup_node/store_version.ml @@ -27,3 +27,33 @@ type t = V0 | V1 let pp ppf v = Format.pp_print_string ppf @@ match v with V0 -> "v0" | V1 -> "v1" + +let encoding = + let open Data_encoding in + conv + (function V0 -> 0 | V1 -> 1) + (function + | 0 -> V0 + | 1 -> V1 + | v -> Format.ksprintf Stdlib.failwith "Unsupported store version %d" v) + (obj1 (req "store_version" int31)) + +let path ~dir = Filename.concat dir "version" + +let read_version_file ~dir = + let open Lwt_result_syntax in + protect @@ fun () -> + let filename = path ~dir in + let*! exists = Lwt_unix.file_exists filename in + if not exists then return_none + else + let* json = Lwt_utils_unix.Json.read_file filename in + return_some (Data_encoding.Json.destruct encoding json) + +let write_version_file ~dir version = + let open Lwt_result_syntax in + protect @@ fun () -> + let filename = path ~dir in + let*! () = Lwt_utils_unix.create_dir dir in + let json = Data_encoding.Json.construct encoding version in + Lwt_utils_unix.Json.write_file filename json diff --git a/src/proto_alpha/lib_sc_rollup_node/store_version.mli b/src/proto_alpha/lib_sc_rollup_node/store_version.mli index 86b8485e19c100a8cf59be262e443f1e684767c5..870c76d05ba28a4e2039bdfa9b4e1db939aaa694 100644 --- a/src/proto_alpha/lib_sc_rollup_node/store_version.mli +++ b/src/proto_alpha/lib_sc_rollup_node/store_version.mli @@ -27,3 +27,9 @@ type t = V0 | V1 (** Pretty-printer for store versions *) val pp : Format.formatter -> t -> unit + +(** Read the version file from [dir]. *) +val read_version_file : dir:string -> t option tzresult Lwt.t + +(** Write a version to the version file in [dir]. *) +val write_version_file : dir:string -> t -> unit tzresult Lwt.t