diff --git a/src/bin_dal_node/daemon.ml b/src/bin_dal_node/daemon.ml index a753e897fe382022c0b64ed09e2fb4b2dcf38833..3fe6f2b00efbe2151ae9777bc66ac0f2dde2f286 100644 --- a/src/bin_dal_node/daemon.ml +++ b/src/bin_dal_node/daemon.ml @@ -53,18 +53,20 @@ let () = (function Cryptobox_initialisation_failed str -> Some str | _ -> None) (fun str -> Cryptobox_initialisation_failed str) -let init_cryptobox unsafe_srs cctxt (module Plugin : Dal_plugin.T) = +let init_cryptobox unsafe_srs (proto_parameters : Dal_plugin.proto_parameters) = let open Cryptobox in let open Lwt_result_syntax in - let* parameters = Plugin.get_constants cctxt#chain cctxt#block cctxt in - let srs_size = if unsafe_srs then Some parameters.slot_size else None in + let srs_size = + if unsafe_srs then Some proto_parameters.cryptobox_parameters.slot_size + else None + in let* () = let find_srs_files () = Tezos_base.Dal_srs.find_trusted_setup_files () in Cryptobox.Config.init_dal ~find_srs_files Cryptobox.Config.{activated = true; srs_size} in - match Cryptobox.make parameters with + match Cryptobox.make proto_parameters.cryptobox_parameters with | Ok cryptobox -> return cryptobox | Error (`Fail msg) -> fail [Cryptobox_initialisation_failed msg] @@ -108,10 +110,13 @@ module Handler = struct | Some plugin -> let (module Plugin : Dal_plugin.T) = plugin in let*! () = Event.emit_protocol_plugin_resolved Plugin.Proto.hash in + let* proto_parameters = + Plugin.get_constants cctxt#chain cctxt#block cctxt + in let* cryptobox = - init_cryptobox config.Configuration.use_unsafe_srs cctxt plugin + init_cryptobox config.Configuration.use_unsafe_srs proto_parameters in - Node_context.set_ready ctxt (module Plugin) cryptobox ; + Node_context.set_ready ctxt (module Plugin) cryptobox proto_parameters ; let*! () = Event.(emit node_is_ready ()) in stopper () ; return_unit @@ -133,7 +138,7 @@ module Handler = struct let handler _stopper (block_hash, (header : Tezos_base.Block_header.t)) = match Node_context.get_status ctxt with | Starting -> return_unit - | Ready {plugin = (module Plugin); _} -> + | Ready {plugin = (module Plugin); proto_parameters; _} -> let* block_info = Plugin.block_info cctxt @@ -148,6 +153,20 @@ module Handler = struct slot_headers (Node_context.get_store ctxt) in + let* attested_slots, unattested_slots = + Plugin.slot_headers_attestation + block_hash + block_info + ~number_of_slots:proto_parameters.number_of_slots + in + let* () = + Slot_manager.update_selected_slot_headers_statuses + ~block_level:header.shell.level + ~attestation_lag:proto_parameters.attestation_lag + attested_slots + unattested_slots + (Node_context.get_store ctxt) + in return_unit in let*! () = Event.(emit layer1_node_tracking_started ()) in @@ -160,8 +179,7 @@ module Handler = struct let new_slot_header ctxt = (* Monitor neighbor DAL nodes and download published slots as shards. *) let open Lwt_result_syntax in - let handler n_cctxt ready_ctxt slot_header = - let cryptobox = ready_ctxt.Node_context.cryptobox in + let handler n_cctxt Node_context.{cryptobox; _} slot_header = let dal_parameters = Cryptobox.parameters cryptobox in let downloaded_shard_ids = 0 @@ -182,7 +200,7 @@ module Handler = struct Slot_manager.save_shards (Node_context.get_store ctxt).shard_store (Node_context.get_store ctxt).slots_watcher - ready_ctxt.Node_context.cryptobox + cryptobox slot_header shards in diff --git a/src/bin_dal_node/node_context.ml b/src/bin_dal_node/node_context.ml index d9de1fe1286948ab75b9669c832c5952ae6332d6..5d3add62f7cbd7fc3afc102d10dd0997c932186b 100644 --- a/src/bin_dal_node/node_context.ml +++ b/src/bin_dal_node/node_context.ml @@ -25,7 +25,11 @@ exception Status_already_ready -type ready_ctxt = {cryptobox : Cryptobox.t; plugin : (module Dal_plugin.T)} +type ready_ctxt = { + cryptobox : Cryptobox.t; + proto_parameters : Dal_plugin.proto_parameters; + plugin : (module Dal_plugin.T); +} type status = Ready of ready_ctxt | Starting @@ -45,9 +49,9 @@ let init config store = in {status = Starting; config; store; neighbors_cctxts} -let set_ready ctxt plugin cryptobox = +let set_ready ctxt plugin cryptobox proto_parameters = match ctxt.status with - | Starting -> ctxt.status <- Ready {plugin; cryptobox} + | Starting -> ctxt.status <- Ready {plugin; cryptobox; proto_parameters} | Ready _ -> raise Status_already_ready type error += Node_not_ready diff --git a/src/bin_dal_node/node_context.mli b/src/bin_dal_node/node_context.mli index 3a88e2b0da7a2a727aa8e4966dfa633e4f5d2403..52cff222e954c9ea2f4fe5bea22516a0ffef8c5c 100644 --- a/src/bin_dal_node/node_context.mli +++ b/src/bin_dal_node/node_context.mli @@ -26,7 +26,11 @@ (** A [ready_ctx] value contains globally needed informations for a running dal node. It is available when both cryptobox is initialized and dal plugin is loaded. *) -type ready_ctxt = {cryptobox : Cryptobox.t; plugin : (module Dal_plugin.T)} +type ready_ctxt = { + cryptobox : Cryptobox.t; + proto_parameters : Dal_plugin.proto_parameters; + plugin : (module Dal_plugin.T); +} (** The status of the dal node *) type status = Ready of ready_ctxt | Starting @@ -42,13 +46,17 @@ val init : Configuration.t -> Store.node_store -> t (** Raised by [set_ready] when the status is already [Ready _] *) exception Status_already_ready -(** [set_ready ctxt plugin dal_constants] updates in place the status - value to [Ready], and initializes the inner [ready_ctxt] value with the given - parameters. +(** [set_ready ctxt plugin cryptobox proto_parameters] updates in place the + status value to [Ready], and initializes the inner [ready_ctxt] value with + the given parameters. @raise Status_already_ready when the status is already [Ready _] *) val set_ready : - t -> (module Tezos_dal_node_lib.Dal_plugin.T) -> Cryptobox.t -> unit + t -> + (module Tezos_dal_node_lib.Dal_plugin.T) -> + Cryptobox.t -> + Dal_plugin.proto_parameters -> + unit type error += Node_not_ready diff --git a/src/bin_dal_node/slot_manager.ml b/src/bin_dal_node/slot_manager.ml index d6e1b704073dc65cd529982495fb800d36f1f8be..10db4d5ed29ed459636fa0bf5422f0a89914c82d 100644 --- a/src/bin_dal_node/slot_manager.ml +++ b/src/bin_dal_node/slot_manager.ml @@ -99,3 +99,12 @@ let find_slot node_store cryptobox commitment = let store_slot_headers ~block_level ~block_hash slot_headers node_store = Store.Legacy.add_slot_headers ~block_level ~block_hash slot_headers node_store + +let update_selected_slot_headers_statuses ~block_level ~attestation_lag + attested_slots unattested_slots node_store = + Store.Legacy.update_selected_slot_headers_statuses + ~block_level + attested_slots + unattested_slots + node_store + ~attestation_lag diff --git a/src/bin_dal_node/slot_manager.mli b/src/bin_dal_node/slot_manager.mli index ef7b195eedc25844bc4558e19046344434e9ea05..147c333b7378cef2b0ec42c10e8f4bcbaaee4e74 100644 --- a/src/bin_dal_node/slot_manager.mli +++ b/src/bin_dal_node/slot_manager.mli @@ -76,3 +76,20 @@ val store_slot_headers : (Dal_plugin.slot_header * Dal_plugin.operation_application_result) list -> Store.node_store -> unit Lwt.t + +(** [update_selected_slot_headers_statuses ~block_level ~attestation_lag + attested_slots unattested_slots store] updates the statuses of the + previously selected slots at level [block_level] - [endorsement_lag] and + that were waiting for attestation. + + Slot headers whose indexes are in [attested_slots] are now set as + {!`Attested} in [store]. Those in [unattested_slots] are marked as + {!`Unattested} in the [store]. +*) +val update_selected_slot_headers_statuses : + block_level:int32 -> + attestation_lag:int -> + [`Attested of Dal_plugin.slot_index list] -> + [`Unattested of Dal_plugin.slot_index list] -> + Store.node_store -> + unit tzresult Lwt.t diff --git a/src/bin_dal_node/store.ml b/src/bin_dal_node/store.ml index e455b8cd5536f02c85631b2ec43802ef2132907c..ef56927d665c4acf7fcc9817ecf04acc1c36301a 100644 --- a/src/bin_dal_node/store.ml +++ b/src/bin_dal_node/store.ml @@ -45,6 +45,8 @@ let info message = let set ~msg store path v = set_exn store path v ~info:(fun () -> info msg) +let remove ~msg store path = remove_exn store path ~info:(fun () -> info msg) + (** Store context *) type node_store = { slots_store : t; @@ -74,6 +76,8 @@ module Legacy = struct module Path : sig type t = string list + val to_string : ?prefix:string -> t -> string + module Commitment : sig val slot : Cryptobox.commitment -> slot_size:int -> Path.t @@ -106,6 +110,10 @@ module Legacy = struct let ( / ) b a = a :: b + let to_string ?prefix p = + let s = String.concat "/" p in + Option.fold ~none:s ~some:(fun pr -> pr ^ s) prefix + module Commitment = struct let root = ["commitments"] @@ -219,7 +227,7 @@ module Legacy = struct Lwt.return_unit) slot_headers - let add_slot_headers ~block_level:_ ~block_hash slot_headers node_store = + let add_slot_headers ~block_level ~block_hash slot_headers node_store = let open Lwt_syntax in let* () = legacy_add_slot_headers ~block_hash slot_headers node_store in let slots_store = node_store.slots_store in @@ -232,6 +240,8 @@ module Legacy = struct let Dal_plugin.{slot_index; commitment; published_level} = slot_header in + (* This invariant should hold. *) + assert (Int32.equal published_level block_level) ; match status with | Dal_plugin.Succeeded -> let index = @@ -247,18 +257,13 @@ module Legacy = struct let* () = set ~msg: - (Printf.sprintf - "add_slot_headers:%s" - (String.concat "/" commitment_path)) + (Path.to_string ~prefix:"add_slot_headers:" commitment_path) slots_store commitment_path data in set - ~msg: - (Printf.sprintf - "add_slot_headers:%s" - (String.concat "/" status_path)) + ~msg:(Path.to_string ~prefix:"add_slot_headers:" status_path) slots_store status_path (Services.Types.header_attestation_status_to_string @@ -269,9 +274,64 @@ module Legacy = struct in let path = Path.Level.other_header_status index commitment in set - ~msg:"add_slot_headers:others:status" + ~msg:(Path.to_string ~prefix:"add_slot_headers:" path) slots_store path (Services.Types.header_status_to_string `Not_selected)) slot_headers + + let check_old_stored_value_is ?old_value ~path store : unit tzresult Lwt.t = + let open Lwt_result_syntax in + let*! data_opt = find store path in + let* data = + match data_opt with + | Some data -> return data + | None -> + failwith + "check_old_value_is: No data found under %s" + (Path.to_string path) + in + match old_value with + | None -> return_unit + | Some expected -> + if String.equal expected data then return_unit + else + failwith "check_old_value_is: expecting %s but got %s" expected data + + let update_slot_headers_attestation ~published_level store slots = + let open Lwt_result_syntax in + let attestation_status, slots = + match slots with + | `Attested l -> (`Attested, l) + | `Unattested l -> (`Unattested, l) + in + let attestation_status = + Services.Types.header_attestation_status_to_string attestation_status + in + let old_value = + Services.Types.header_attestation_status_to_string + `Waiting_for_attestations + in + List.iter_es + (fun slot_index -> + let index = Services.Types.{slot_level = published_level; slot_index} in + let status_path = Path.Level.accepted_header_status index in + let* () = + check_old_stored_value_is ~old_value ~path:status_path store + in + let msg = + Path.to_string ~prefix:"update_slot_headers_attestation:" status_path + in + let*! () = remove ~msg store status_path in + let*! () = set ~msg store status_path attestation_status in + return_unit) + slots + + let update_selected_slot_headers_statuses ~block_level ~attestation_lag + attested unattested node_store = + let open Lwt_result_syntax in + let store = node_store.slots_store in + let published_level = Int32.(sub block_level (of_int attestation_lag)) in + let* () = update_slot_headers_attestation ~published_level store attested in + update_slot_headers_attestation ~published_level store unattested end diff --git a/src/lib_dal_node/dal_plugin.ml b/src/lib_dal_node/dal_plugin.ml index 104dbf770cebe0bd5815bad9d0f1cabc762e8cae..ad53881fa509c075f1faf000f07afd2b94a80b2e 100644 --- a/src/lib_dal_node/dal_plugin.ml +++ b/src/lib_dal_node/dal_plugin.ml @@ -33,6 +33,15 @@ type slot_header = { commitment : Tezos_crypto_dal.Cryptobox.Verifier.commitment; } +type proto_parameters = { + feature_enable : bool; + number_of_slots : int; + attestation_lag : int; + availability_threshold : int; + cryptobox_parameters : Tezos_crypto_dal.Cryptobox.Verifier.parameters; + blocks_per_epoch : int32; +} + module type T = sig module Proto : Registered_protocol.T @@ -49,12 +58,19 @@ module type T = sig Tezos_shell_services.Chain_services.chain -> Tezos_shell_services.Block_services.block -> Client_context.full -> - Tezos_crypto_dal.Cryptobox.Verifier.parameters tzresult Lwt.t + proto_parameters tzresult Lwt.t val get_published_slot_headers : block_info -> (slot_header * operation_application_result) list tzresult Lwt.t + val slot_headers_attestation : + Tezos_crypto.Block_hash.t -> + block_info -> + number_of_slots:int -> + ([`Attested of slot_index list] * [`Unattested of slot_index list]) tzresult + Lwt.t + module RPC : sig val rpc_services : reveal_data_dir:string -> diff --git a/src/lib_dal_node/dal_plugin.mli b/src/lib_dal_node/dal_plugin.mli index 3408f6ecf2745bfc118f7bc1f1a3cfe41f1deb25..f8e69d05e75fba76e8bf7d4282af9acc4e1c4474 100644 --- a/src/lib_dal_node/dal_plugin.mli +++ b/src/lib_dal_node/dal_plugin.mli @@ -42,6 +42,15 @@ type slot_header = { commitment : Tezos_crypto_dal.Cryptobox.Verifier.commitment; } +type proto_parameters = { + feature_enable : bool; + number_of_slots : int; + attestation_lag : int; + availability_threshold : int; + cryptobox_parameters : Tezos_crypto_dal.Cryptobox.Verifier.parameters; + blocks_per_epoch : int32; +} + module type T = sig module Proto : Registered_protocol.T @@ -62,12 +71,27 @@ module type T = sig Tezos_shell_services.Chain_services.chain -> Tezos_shell_services.Block_services.block -> Client_context.full -> - Tezos_crypto_dal.Cryptobox.Verifier.parameters tzresult Lwt.t + proto_parameters tzresult Lwt.t val get_published_slot_headers : block_info -> (slot_header * operation_application_result) list tzresult Lwt.t + (** [slot_headers_attestation hash block_info number_of_slots] reads the + metadata of the given [block_info] and constructs two lists of attested + and unattested slots depending on the value of dal_attestation bitset. + The value of [number_of_slots] indicates the current maximum number of + slots on DAL per level. + + Fails with [Cannot_read_block_metadata] if [block_info]'s metadata are + stripped. *) + val slot_headers_attestation : + Tezos_crypto.Block_hash.t -> + block_info -> + number_of_slots:int -> + ([`Attested of slot_index list] * [`Unattested of slot_index list]) tzresult + Lwt.t + module RPC : sig val rpc_services : reveal_data_dir:string -> diff --git a/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml b/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml index 3a1af0ef89506a416ccdac1f1be7fc14bfb4eb54..fdf50dc71a1693c9e9208c112e8587afbfa67e95 100644 --- a/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml +++ b/src/proto_alpha/bin_sc_rollup_node/dal_slots_tracker.ml @@ -140,7 +140,7 @@ let to_slot_index_list (constants : Constants.Parametric.t) bitset = then Dal.Slot_index.to_int will always return a defined value. See `src/proto_alpha/lib_protocol/constants_repr.ml`. *) - List.filter_map Dal.Slot_index.of_int filtered + List.filter_map Dal.Slot_index.of_int_opt filtered (* DAL/FIXME: https://gitlab.com/tezos/tezos/-/issues/4139. Use a shared storage between dal and rollup node to store slots data. diff --git a/src/proto_alpha/lib_dal/dal_plugin_registration.ml b/src/proto_alpha/lib_dal/dal_plugin_registration.ml index 3308cda47b34c875a45f7f56032cbfcde2167c5e..6fe57fff1d28c10c64a82a832d8f038343fb8e15 100644 --- a/src/proto_alpha/lib_dal/dal_plugin_registration.ml +++ b/src/proto_alpha/lib_dal/dal_plugin_registration.ml @@ -23,16 +23,40 @@ (* *) (*****************************************************************************) +open Protocol +open Alpha_context + module Plugin = struct module Proto = Registerer.Registered type block_info = Protocol_client_context.Alpha_block_services.block_info - let get_constants chain block ctxt = + let parametric_constants chain block ctxt = let cpctxt = new Protocol_client_context.wrap_full ctxt in + Protocol.Constants_services.parametric cpctxt (chain, block) + + let get_constants chain block ctxt = let open Lwt_result_syntax in - let* constants = Protocol.Constants_services.all cpctxt (chain, block) in - return constants.parametric.dal.cryptobox_parameters + let* parametric = parametric_constants chain block ctxt in + let { + Constants.Parametric.feature_enable; + number_of_slots; + attestation_lag; + availability_threshold; + cryptobox_parameters; + blocks_per_epoch; + } = + parametric.dal + in + return + { + Dal_plugin.feature_enable; + number_of_slots; + attestation_lag; + availability_threshold; + cryptobox_parameters; + blocks_per_epoch; + } let block_info ?chain ?block ~metadata ctxt = let cpctxt = new Protocol_client_context.wrap_full ctxt in @@ -75,6 +99,29 @@ module Plugin = struct }, status )) + let slot_headers_attestation hash (block : block_info) ~number_of_slots = + let open Lwt_result_syntax in + let*? metadata = + Option.to_result + block.metadata + ~none:(TzTrace.make @@ Layer1_services.Cannot_read_block_metadata hash) + in + let confirmed_slots = + Option.value + ~default:Dal.Attestation.empty + metadata.protocol_data.dal_attestation + in + let*? all_slots = + Dal.Slot_index.slots_range ~lower:0 ~upper:(number_of_slots - 1) + |> Environment.wrap_tzresult + in + let attested, unattested = + List.partition (Dal.Attestation.is_attested confirmed_slots) all_slots + in + return + ( `Attested (Dal.Slot_index.to_int_list attested), + `Unattested (Dal.Slot_index.to_int_list unattested) ) + module RPC = RPC end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index f106181b72242666c0f7287aa82bbdd67359068d..55bf96a09fbe1c194f88a8412f772f6115fc5972 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2920,13 +2920,21 @@ module Dal : sig val encoding : t Data_encoding.t - val of_int : int -> t option + val of_int_opt : int -> t option + + val of_int : int -> t tzresult val to_int : t -> int + val to_int_list : t list -> int list + val compare : t -> t -> int val equal : t -> t -> bool + + val slots_range : lower:int -> upper:int -> t list tzresult + + val slots_range_opt : lower:int -> upper:int -> t list option end (** This module re-exports definitions from {!Dal_attestation_repr} and diff --git a/src/proto_alpha/lib_protocol/dal_apply.ml b/src/proto_alpha/lib_protocol/dal_apply.ml index 7942e74f788b0a6d3af03358ffa4898d7838803b..833d788276ed86bee23f144e67d44ae015a65531 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.ml +++ b/src/proto_alpha/lib_protocol/dal_apply.ml @@ -40,7 +40,7 @@ let only_if_dal_feature_enabled ctxt ~default f = let slot_of_int_e n = let open Result_syntax in - match Dal.Slot_index.of_int n with + match Dal.Slot_index.of_int_opt n with | None -> tzfail Dal_errors.Dal_slot_index_above_hard_limit | Some slot_index -> return slot_index diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index cf43da6693c91601364d2996bb037ca8ecf44f6c..05cf0e5fabccf88e250102297cb28bea42355e06 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -67,16 +67,58 @@ module Index = struct let zero = 0 + type error += Invalid_slot_index of {given : int; min : int; max : int} + + let () = + let open Data_encoding in + register_error_kind + `Permanent + ~id:"dal_slot_repr.index.invalid_index" + ~title:"Invalid Dal slot index" + ~description: + "The given index is out of range of representable slot indices" + ~pp:(fun ppf (given, min, max) -> + Format.fprintf + ppf + "The given index %d is out of range of representable slot indices \ + [%d, %d]" + given + min + max) + (obj3 (req "given" int31) (req "min" int31) (req "max" int31)) + (function + | Invalid_slot_index {given; min; max} -> Some (given, min, max) + | _ -> None) + (fun (given, min, max) -> Invalid_slot_index {given; min; max}) + + let check_is_in_range slot_index = + error_unless + Compare.Int.(slot_index >= zero && slot_index <= max_value) + (Invalid_slot_index {given = slot_index; min = zero; max = max_value}) + let of_int slot_index = - if Compare.Int.(slot_index <= max_value && slot_index >= zero) then - Some slot_index - else None + let open Result_syntax in + let* () = check_is_in_range slot_index in + return slot_index + + let of_int_opt slot_index = Option.of_result @@ of_int slot_index let to_int slot_index = slot_index [@@ocaml.inline always] + let to_int_list l = l [@@ocaml.inline always] + let compare = Compare.Int.compare let equal = Compare.Int.equal + + let slots_range ~lower ~upper = + let open Result_syntax in + let* () = check_is_in_range lower in + let* () = check_is_in_range upper in + return Misc.(lower --> upper) + + let slots_range_opt ~lower ~upper = + Option.of_result @@ slots_range ~lower ~upper end module Header = struct diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index b4db6978446c40e8421be686e1a97a665c4a28a4..29fc7d729c8da95db6ebf14ab63304457b61c3eb 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -89,6 +89,8 @@ end module Index : sig type t + type error += Invalid_slot_index of {given : int; min : int; max : int} + val encoding : t Data_encoding.t val pp : Format.formatter -> t -> unit @@ -97,14 +99,33 @@ module Index : sig val max_value : t - (** [of_int n] constructs a`Slot_index.t` *) - val of_int : int -> t option + (** [of_int_opt n] constructs a value of type {!t} from [n]. Returns {!None} + in case the given value is not in the interval [zero, max_value]. *) + val of_int_opt : int -> t option + + (** [of_int n] constructs a value of type {!t} from [n]. Returns + {!Invalid_slot_index} in case the given value is not in the interval [zero, + max_value]. *) + val of_int : int -> t tzresult val to_int : t -> int + val to_int_list : t list -> int list + val compare : t -> t -> int val equal : t -> t -> bool + + (** [slots_range ~lower ~upper] returns the list of slots indexes between + [lower] and [upper]. + + If [lower] is negative or [upper] is bigger than [max_value], the function + returns {!Invalid_slot_index}. *) + val slots_range : lower:int -> upper:int -> t list tzresult + + (** [slots_range_opt ~lower ~upper] is similar to {!slots_range}, but return + {None} in case of error instead of {!Invalid_slot_index}. *) + val slots_range_opt : lower:int -> upper:int -> t list option end module Header : sig diff --git a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml index 55c930c3adc8b51d7fa1576f2b455db4a80fa6f8..3fd65bd56cd67163f73f191ec26ab4d3e5721840 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml @@ -1250,7 +1250,7 @@ module Make (Context : P) : let open Option_syntax in let* index = Option.map Int32.to_int @@ Int32.of_string_opt slot_str in if Compare.Int.(index < 0 || index >= number_of_slots) then None - else Dal_slot_repr.Index.of_int index + else Dal_slot_repr.Index.of_int_opt index in let mk_page_index page_str = let open Option_syntax in diff --git a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml index c6624b11513c5959e39f0fccdce5fb9bf387c16e..a3e838947f8965e717afa06c0334cd7924d8ac3f 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml @@ -142,7 +142,7 @@ struct let succ_slot_index index = Option.value_f - S.Index.(of_int (to_int index + 1)) + S.Index.(of_int_opt (to_int index + 1)) ~default:(fun () -> S.Index.zero) let next_char c = Char.(chr ((code c + 1) mod 255)) diff --git a/src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.ml b/src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.ml index 4d956049b5e407e738b521eb5fffbe6c7d45a7d4..3f708dfe1a493833b4eeef1553f7786ca2004c6c 100644 --- a/src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.ml +++ b/src/proto_alpha/lib_protocol/test/pbt/test_dal_slot_proof.ml @@ -71,8 +71,9 @@ struct (* Make and insert a slot. *) let add_slot level sindex (cell, cache, slots_info) skip_slot = let index = - Option.value_f (Dal_slot_repr.Index.of_int sindex) ~default:(fun () -> - assert false) + Option.value_f + (Dal_slot_repr.Index.of_int_opt sindex) + ~default:(fun () -> assert false) in let* _data, poly, slot = mk_slot ~level ~index () in let* cell, cache = diff --git a/src/proto_alpha/lib_protocol/test/pbt/test_sc_rollup_encoding.ml b/src/proto_alpha/lib_protocol/test/pbt/test_sc_rollup_encoding.ml index 5dcda40637ded56b71c9dc507a2f63fe6e77cec0..db7af6fc4885220530e0361c15ad697aaa97f4df 100644 --- a/src/proto_alpha/lib_protocol/test/pbt/test_sc_rollup_encoding.ml +++ b/src/proto_alpha/lib_protocol/test/pbt/test_sc_rollup_encoding.ml @@ -133,7 +133,9 @@ let gen_dal_slots_history () = genesis cell's level in the skip list. *) succ @@ try of_int32_exn (Int32.of_int level) with _ -> root) in - let index = Index.(of_int slot_index |> Option.value ~default:zero) in + let index = + Index.(of_int_opt slot_index |> Option.value ~default:zero) + in Header.{id = {published_level; index}; commitment = Commitment.zero}) list in diff --git a/src/proto_alpha/lib_sc_rollup/sc_rollup_services.ml b/src/proto_alpha/lib_sc_rollup/sc_rollup_services.ml index ad563962fe176f0932554e473576fcc55658366a..8a38c2910f6fd5b22332146f6e3cba9b0089f7af 100644 --- a/src/proto_alpha/lib_sc_rollup/sc_rollup_services.ml +++ b/src/proto_alpha/lib_sc_rollup/sc_rollup_services.ml @@ -550,7 +550,7 @@ module Global = struct raise (Invalid (Format.asprintf "Invalid parameter (%d)" i)) in query (fun raw_index raw_page -> - let index = req "index" Dal.Slot_index.of_int raw_index in + let index = req "index" Dal.Slot_index.of_int_opt raw_index in let page = req "page" (fun p -> p) raw_page in match index with | None -> invalid_parameter @@ Option.value ~default:0 raw_index