From bb779e4dc454c5a619a0396dddb4273bb2e056af Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 22 Oct 2025 09:09:59 +0200 Subject: [PATCH 01/13] Dal/Node: refactoring --- src/lib_dal_node/store.ml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/lib_dal_node/store.ml b/src/lib_dal_node/store.ml index 416504cf6bbc..adcb2996fb73 100644 --- a/src/lib_dal_node/store.ml +++ b/src/lib_dal_node/store.ml @@ -28,13 +28,7 @@ module Profiler = (val Profiler.wrap Dal_profiler.dal_profiler) (** FIFO-keyed map with slot_id as keys. *) module Slot_map = Aches.Vache.Map (Aches.Vache.FIFO_Precise) (Aches.Vache.Strong) - (struct - type t = Types.Slot_id.t - - let equal = Types.Slot_id.equal - - let hash = Types.Slot_id.hash - end) + (Types.Slot_id) module Version = struct type t = int -- GitLab From 62fcb88e94d97701c3217ac4fd3e3a0fb09ca6f1 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 8 Oct 2025 17:02:37 +0200 Subject: [PATCH 02/13] DAL/Node: extend dal_node_client with get_slot_status service --- src/lib_dal_node/dal_node_client.ml | 8 ++++++++ src/lib_dal_node/dal_node_client.mli | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/src/lib_dal_node/dal_node_client.ml b/src/lib_dal_node/dal_node_client.ml index dc8fd5100a58..2ba1a8dff8e0 100644 --- a/src/lib_dal_node/dal_node_client.ml +++ b/src/lib_dal_node/dal_node_client.ml @@ -81,3 +81,11 @@ let post_slot cctxt ?slot_index slot = () query slot [@profiler.aggregate_s {verbosity = Notice} "post_slot"]) + +let get_slot_status cctxt (slot_id : Types.slot_id) = + call + cctxt + Services.get_slot_status + (((), slot_id.slot_level), slot_id.slot_index) + () + () diff --git a/src/lib_dal_node/dal_node_client.mli b/src/lib_dal_node/dal_node_client.mli index 813ae1c8cf87..39c4a3cbff7e 100644 --- a/src/lib_dal_node/dal_node_client.mli +++ b/src/lib_dal_node/dal_node_client.mli @@ -59,3 +59,10 @@ val post_slot : ?slot_index:Tezos_dal_node_services.Types.slot_index -> string -> (Cryptobox.commitment * Cryptobox.commitment_proof) tzresult Lwt.t + +(** [get_slot_status cctxt slot_id] returns the attestation + info (status and lag) of the slot whose id is given. *) +val get_slot_status : + cctxt -> + Tezos_dal_node_services.Types.slot_id -> + Tezos_dal_node_services.Types.header_status tzresult Lwt.t -- GitLab From e400bb63a4917cb7f0d8e04e54a1335ce58be223 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Fri, 7 Nov 2025 08:59:29 +0100 Subject: [PATCH 03/13] DAL/Rollups: Use the DAL node to fetch the attestation status of slots The RPC also fetchs the attestation lag, but it's not used yet. --- .../lib_sc_rollup_node/dal_pages_request.ml | 133 ++++-------------- 1 file changed, 24 insertions(+), 109 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index 20baa611e01a..58d1640fc46f 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -115,102 +115,19 @@ let download_confirmed_slot_pages {Node_context.dal_cctxt; _} ~published_level dal_cctxt {slot_level = Raw_level.to_int32 published_level; slot_index = index} -module Slots_statuses_cache = - Aches.Vache.Map (Aches.Vache.FIFO_Precise) (Aches.Vache.Strong) - (struct - type t = Dal.Slot.Header.id - - let equal = Dal.Slot.Header.slot_id_equal - - let hash id = Hashtbl.hash id - end) - -let download_skip_list_cells_of_level node_ctxt ~attested_level = - Plugin.RPC.Dal.skip_list_cells_of_level - (new Protocol_client_context.wrap_full node_ctxt.Node_context.cctxt) - (`Main, `Level attested_level) - () - -(* We have currently 32 slots per level. We retain the information for 32 levels - (assuming no reorgs with different payload occur). *) -let skip_list_cells_content_cache = - (* Attestation lag * number of slots * 32 retention levels, assuming no - reorgs. *) - let attestation_lag = 8 in - let number_of_slots = 32 in - let retention_levels = 32 in - Slots_statuses_cache.create - (attestation_lag * number_of_slots * retention_levels) - -let dal_skip_list_cell_content_of_slot_id node_ctxt - (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) slot_id - = - let open Lwt_result_syntax in - let attested_level = - Int32.add - (Raw_level.to_int32 slot_id.Dal.Slot.Header.published_level) - (Int32.of_int dal_constants.attestation_lag) - in - let* attested_level_hash = - Node_context.hash_of_level node_ctxt attested_level - in - match Slots_statuses_cache.find_opt skip_list_cells_content_cache slot_id with - | Some (cell_content, block_hash) - when Block_hash.equal attested_level_hash block_hash -> - return cell_content - | None | Some _ -> ( - let* hash_with_cells = - download_skip_list_cells_of_level node_ctxt ~attested_level - in - List.iter - (fun (_hash, cell) -> - let content = Dal.Slots_history.content cell in - Slots_statuses_cache.replace - skip_list_cells_content_cache - (Dal.Slots_history.content_id content).header_id - (content, attested_level_hash)) - hash_with_cells ; - (* The [find] below validates the fact that we fetched the info of - commitments published at level [slot_id.published_level]. *) - match - Slots_statuses_cache.find_opt skip_list_cells_content_cache slot_id - with - | Some (cell_content, block_hash) - when Block_hash.equal attested_level_hash block_hash -> - return cell_content - | None -> - Stdlib.failwith - (Format.asprintf - "Unreachable: We expect to find some data for slot %a, but got \ - none" - Dal.Slot.Header.pp_id - slot_id) - | Some (_, got_hash) -> - Stdlib.failwith - (Format.asprintf - "Unreachable: We expect to find some data for slot %a \ - associated to block hash %a, but got data associated to block \ - hash %a" - Dal.Slot.Header.pp_id - slot_id - Block_hash.pp_short - attested_level_hash - Block_hash.pp_short - got_hash)) - -let slot_attestation_status ?attestation_threshold_percent - ?restricted_commitments_publishers node_ctxt dal_constants slot_id = - let open Lwt_result_syntax in - let* cell_content = - dal_skip_list_cell_content_of_slot_id node_ctxt dal_constants slot_id - in - let commitment_res = - Dal.Slots_history.is_commitment_attested - ~attestation_threshold_percent - ~restricted_commitments_publishers - cell_content +(* Adaptive DAL is not supported anymore *) +let get_slot_header_attestation_info {Node_context.dal_cctxt; _} + ~published_level ~index = + (* TODO: add a cache for this Query, but not for the Not_indexed case. *) + let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ dal_cctxt in + let slot_id = + Slot_id. + { + slot_level = Raw_level.to_int32 published_level; + slot_index = Dal.Slot_index.to_int index; + } in - return @@ if Option.is_some commitment_res then `Attested else `Unattested + Dal_node_client.get_slot_status dal_cctxt slot_id let get_page node_ctxt ~inbox_level page_id = let open Environment.Error_monad.Lwt_result_syntax in @@ -310,26 +227,29 @@ let slot_pages slot_id then return_none else - let* status = slot_attestation_status node_ctxt dal_constants slot_id in + let* status = + get_slot_header_attestation_info node_ctxt ~published_level ~index + in match status with - | `Attested -> + | `Attested _attestation_lag -> let index = Sc_rollup_proto_types.Dal.Slot_index.to_octez index in let* pages = download_confirmed_slot_pages node_ctxt ~published_level ~index in return (Some pages) - | `Unattested -> return_none + | `Unattested | `Waiting_attestation | `Unpublished -> return_none let page_content (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) - ~dal_activation_level ~inbox_level node_ctxt ~attestation_threshold_percent - ~restricted_commitments_publishers page_id ~dal_attested_slots_validity_lag - = + ~dal_activation_level ~inbox_level node_ctxt + ~attestation_threshold_percent:_ ~restricted_commitments_publishers:_ + page_id ~dal_attested_slots_validity_lag = let open Lwt_result_syntax in let Node_context.{genesis_info = {level = origination_level; _}; l1_ctxt; _} = node_ctxt in let* chain_id = Layer1.get_chain_id l1_ctxt in + let Dal.Slot.Header.{published_level; index} = page_id.Dal.Page.slot_id in if not @@ page_id_is_valid @@ -343,13 +263,8 @@ let page_content then return_none else let* status = - slot_attestation_status - ?attestation_threshold_percent - ?restricted_commitments_publishers - node_ctxt - dal_constants - page_id.Dal.Page.slot_id + get_slot_header_attestation_info node_ctxt ~published_level ~index in match status with - | `Attested -> get_page node_ctxt ~inbox_level page_id - | `Unattested -> return_none + | `Attested _attestation_lag -> get_page node_ctxt ~inbox_level page_id + | `Unattested | `Waiting_attestation | `Unpublished -> return_none -- GitLab From 94af98efdc9816d65a4d769d06b3a186e73ab9b9 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Fri, 7 Nov 2025 09:02:34 +0100 Subject: [PATCH 04/13] DAL/Rollups: page_id_is_valid and slot_id_is_valid take individual DAL constants as args --- .../lib_sc_rollup_node/dal_pages_request.ml | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index 58d1640fc46f..a2a284aaf498 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -153,8 +153,7 @@ let get_page node_ctxt ~inbox_level page_id = in Lwt.return @@ Environment.wrap_tzresult res -let slot_id_is_valid chain_id - (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) +let slot_id_is_valid chain_id ~dal_attestation_lag ~number_of_slots ~dal_activation_level ~origination_level ~inbox_level slot_id ~dal_attested_slots_validity_lag = let open Alpha_context in @@ -170,9 +169,7 @@ let slot_id_is_valid chain_id else dal_activation_level in Result.is_ok - (Dal.Slot_index.check_is_in_range - ~number_of_slots:dal_constants.number_of_slots - slot_id.Dal.index) + (Dal.Slot_index.check_is_in_range ~number_of_slots slot_id.Dal.index) && let origination_level_res = Raw_level.of_int32 origination_level in let commit_inbox_level_res = Raw_level.of_int32 inbox_level in @@ -180,25 +177,21 @@ let slot_id_is_valid chain_id | Ok origination_level, Ok commit_inbox_level -> Alpha_context.Sc_rollup.Proof.Dal_helpers.import_level_is_valid ~dal_activation_level - ~dal_attestation_lag:dal_constants.attestation_lag + ~dal_attestation_lag ~origination_level ~commit_inbox_level ~dal_attested_slots_validity_lag ~published_level:slot_id.published_level | _ -> false -let page_id_is_valid chain_id - (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) - ~dal_activation_level ~origination_level ~inbox_level +let page_id_is_valid chain_id ~dal_attestation_lag ~number_of_slots + ~number_of_pages ~dal_activation_level ~origination_level ~inbox_level Dal.Page.{slot_id; page_index} ~dal_attested_slots_validity_lag = - Result.is_ok - (Dal.Page.Index.check_is_in_range - ~number_of_pages: - (Dal.Page.pages_per_slot dal_constants.cryptobox_parameters) - page_index) + Result.is_ok (Dal.Page.Index.check_is_in_range ~number_of_pages page_index) && slot_id_is_valid chain_id - dal_constants + ~dal_attestation_lag + ~number_of_slots ~dal_activation_level ~origination_level ~inbox_level @@ -219,7 +212,8 @@ let slot_pages not @@ slot_id_is_valid chain_id - dal_constants + ~dal_attestation_lag:dal_constants.attestation_lag + ~number_of_slots:dal_constants.number_of_slots ~dal_activation_level ~origination_level ~inbox_level @@ -254,7 +248,10 @@ let page_content not @@ page_id_is_valid chain_id - dal_constants + ~dal_attestation_lag:dal_constants.attestation_lag + ~number_of_slots:dal_constants.number_of_slots + ~number_of_pages: + (Dal.Page.pages_per_slot dal_constants.cryptobox_parameters) ~dal_activation_level ~origination_level ~inbox_level -- GitLab From d52527937f42f7b4f3ed681472efc786485f5705 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Fri, 7 Nov 2025 09:04:17 +0100 Subject: [PATCH 05/13] DAL/Rollups: page_id_is_valid and slot_id_is_valid use the right attestation_lag --- .../lib_sc_rollup_node/dal_pages_request.ml | 80 +++++++++---------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index a2a284aaf498..4dd20d099c25 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -208,30 +208,30 @@ let slot_pages in let* chain_id = Layer1.get_chain_id l1_ctxt in let Dal.Slot.Header.{published_level; index} = slot_id in - if - not - @@ slot_id_is_valid - chain_id - ~dal_attestation_lag:dal_constants.attestation_lag - ~number_of_slots:dal_constants.number_of_slots - ~dal_activation_level - ~origination_level - ~inbox_level - ~dal_attested_slots_validity_lag - slot_id - then return_none - else - let* status = - get_slot_header_attestation_info node_ctxt ~published_level ~index - in - match status with - | `Attested _attestation_lag -> + let* status = + get_slot_header_attestation_info node_ctxt ~published_level ~index + in + match status with + | `Attested attestation_lag -> + if + not + @@ slot_id_is_valid + chain_id + ~dal_attestation_lag:attestation_lag + ~number_of_slots:dal_constants.number_of_slots + ~dal_activation_level + ~origination_level + ~inbox_level + ~dal_attested_slots_validity_lag + slot_id + then return_none + else let index = Sc_rollup_proto_types.Dal.Slot_index.to_octez index in let* pages = download_confirmed_slot_pages node_ctxt ~published_level ~index in return (Some pages) - | `Unattested | `Waiting_attestation | `Unpublished -> return_none + | `Unattested | `Waiting_attestation | `Unpublished -> return_none let page_content (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) @@ -244,24 +244,24 @@ let page_content in let* chain_id = Layer1.get_chain_id l1_ctxt in let Dal.Slot.Header.{published_level; index} = page_id.Dal.Page.slot_id in - if - not - @@ page_id_is_valid - chain_id - ~dal_attestation_lag:dal_constants.attestation_lag - ~number_of_slots:dal_constants.number_of_slots - ~number_of_pages: - (Dal.Page.pages_per_slot dal_constants.cryptobox_parameters) - ~dal_activation_level - ~origination_level - ~inbox_level - ~dal_attested_slots_validity_lag - page_id - then return_none - else - let* status = - get_slot_header_attestation_info node_ctxt ~published_level ~index - in - match status with - | `Attested _attestation_lag -> get_page node_ctxt ~inbox_level page_id - | `Unattested | `Waiting_attestation | `Unpublished -> return_none + let* status = + get_slot_header_attestation_info node_ctxt ~published_level ~index + in + match status with + | `Attested attestation_lag -> + if + not + @@ page_id_is_valid + chain_id + ~dal_attestation_lag:attestation_lag + ~number_of_slots:dal_constants.number_of_slots + ~number_of_pages: + (Dal.Page.pages_per_slot dal_constants.cryptobox_parameters) + ~dal_activation_level + ~origination_level + ~inbox_level + ~dal_attested_slots_validity_lag + page_id + then return_none + else get_page node_ctxt ~inbox_level page_id + | `Unattested | `Waiting_attestation | `Unpublished -> return_none -- GitLab From 75d9c27a5c7a2cdea3f0d59f95707b0a017e7514 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Fri, 7 Nov 2025 09:06:09 +0100 Subject: [PATCH 06/13] DAL/Rollups: refactor get_pages_slots: Don't cache errors --- .../lib_sc_rollup_node/dal_pages_request.ml | 55 ++++++++----------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index 4dd20d099c25..5a13a6eaa764 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -25,6 +25,7 @@ open Protocol open Alpha_context +module Slot_id = Tezos_dal_node_services.Types.Slot_id (** If a slot, published at some level L, is expected to be confirmed at level L+D then, once the confirmation level is over, the rollup node is supposed to: @@ -83,37 +84,23 @@ module Event = struct ~pp5:pp_content_elipsis end -module Slot_id = struct - include Tezos_dal_node_services.Types.Slot_id +module Slot_id_cache = + Aches.Vache.Map (Aches.Vache.FIFO_Precise) (Aches.Vache.Strong) (Slot_id) - let equal id1 id2 = Comparable.compare id1 id2 = 0 - - let hash id = Hashtbl.hash id -end - -(* The cache allows to not fetch pages on the DAL node more than necessary. *) -module Pages_cache = - Aches_lwt.Lache.Make (Aches.Rache.Transfer (Aches.Rache.LRU) (Slot_id)) - -let get_slot_pages = - let pages_cache = - Pages_cache.create 16 - (* 130MB *) - in - fun dal_cctxt slot_id -> - Pages_cache.bind_or_put - pages_cache - slot_id - (Dal_node_client.get_slot_pages dal_cctxt) - Lwt.return - -let download_confirmed_slot_pages {Node_context.dal_cctxt; _} ~published_level - ~index = - let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ dal_cctxt in - (* DAL must be configured for this point to be reached *) - get_slot_pages - dal_cctxt - {slot_level = Raw_level.to_int32 published_level; slot_index = index} +let download_confirmed_slot_pages = + let open Lwt_result_syntax in + let cache = Slot_id_cache.create 32 in + fun dal_cctxt ~published_level ~index -> + let slot_id = + Slot_id. + {slot_level = Raw_level.to_int32 published_level; slot_index = index} + in + match Slot_id_cache.find_opt cache slot_id with + | Some pages -> return pages + | None -> + let+ res = Dal_node_client.get_slot_pages dal_cctxt slot_id in + Slot_id_cache.replace cache slot_id res ; + res (* Adaptive DAL is not supported anymore *) let get_slot_header_attestation_info {Node_context.dal_cctxt; _} @@ -207,6 +194,8 @@ let slot_pages node_ctxt in let* chain_id = Layer1.get_chain_id l1_ctxt in + (* DAL must be configured for this point to be reached *) + let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ node_ctxt.dal_cctxt in let Dal.Slot.Header.{published_level; index} = slot_id in let* status = get_slot_header_attestation_info node_ctxt ~published_level ~index @@ -228,7 +217,7 @@ let slot_pages else let index = Sc_rollup_proto_types.Dal.Slot_index.to_octez index in let* pages = - download_confirmed_slot_pages node_ctxt ~published_level ~index + download_confirmed_slot_pages dal_cctxt ~published_level ~index in return (Some pages) | `Unattested | `Waiting_attestation | `Unpublished -> return_none @@ -243,6 +232,8 @@ let page_content node_ctxt in let* chain_id = Layer1.get_chain_id l1_ctxt in + (* DAL must be configured for this point to be reached *) + let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ node_ctxt.dal_cctxt in let Dal.Slot.Header.{published_level; index} = page_id.Dal.Page.slot_id in let* status = get_slot_header_attestation_info node_ctxt ~published_level ~index @@ -263,5 +254,5 @@ let page_content ~dal_attested_slots_validity_lag page_id then return_none - else get_page node_ctxt ~inbox_level page_id + else get_page dal_cctxt ~inbox_level page_id | `Unattested | `Waiting_attestation | `Unpublished -> return_none -- GitLab From ba423364e16fbde6f654a76395eabac7a388a5aa Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 22 Oct 2025 10:19:46 +0200 Subject: [PATCH 07/13] DAL/Rollups: add a cache for get_slot_header_attestation_info, But we don't cache transient statuses, like "Waiting_for_attestation" --- .../lib_sc_rollup_node/dal_pages_request.ml | 36 +++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index 5a13a6eaa764..83b4df2a44de 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -103,18 +103,26 @@ let download_confirmed_slot_pages = res (* Adaptive DAL is not supported anymore *) -let get_slot_header_attestation_info {Node_context.dal_cctxt; _} - ~published_level ~index = - (* TODO: add a cache for this Query, but not for the Not_indexed case. *) - let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ dal_cctxt in - let slot_id = - Slot_id. - { - slot_level = Raw_level.to_int32 published_level; - slot_index = Dal.Slot_index.to_int index; - } - in - Dal_node_client.get_slot_status dal_cctxt slot_id +let get_slot_header_attestation_info = + let open Lwt_result_syntax in + let cache = Slot_id_cache.create 160 in + fun dal_cctxt ~published_level ~index -> + let slot_id = + Slot_id. + { + slot_level = Raw_level.to_int32 published_level; + slot_index = Dal.Slot_index.to_int index; + } + in + match Slot_id_cache.find_opt cache slot_id with + | Some pages -> return pages + | None -> + let+ res = Dal_node_client.get_slot_status dal_cctxt slot_id in + (match res with + | `Attested _ | `Unattested | `Unpublished -> + Slot_id_cache.replace cache slot_id res + | `Waiting_attestation -> ()) ; + res let get_page node_ctxt ~inbox_level page_id = let open Environment.Error_monad.Lwt_result_syntax in @@ -198,7 +206,7 @@ let slot_pages let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ node_ctxt.dal_cctxt in let Dal.Slot.Header.{published_level; index} = slot_id in let* status = - get_slot_header_attestation_info node_ctxt ~published_level ~index + get_slot_header_attestation_info dal_cctxt ~published_level ~index in match status with | `Attested attestation_lag -> @@ -236,7 +244,7 @@ let page_content let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ node_ctxt.dal_cctxt in let Dal.Slot.Header.{published_level; index} = page_id.Dal.Page.slot_id in let* status = - get_slot_header_attestation_info node_ctxt ~published_level ~index + get_slot_header_attestation_info dal_cctxt ~published_level ~index in match status with | `Attested attestation_lag -> -- GitLab From ea09cb73f3ac22cb19001079cfd06eec8e65e48c Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 22 Oct 2025 10:53:31 +0200 Subject: [PATCH 08/13] Dal/Rollups: don't decide to import a page or not for a slot waiting for attestation --- .../lib_sc_rollup_node/dal_pages_request.ml | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index 83b4df2a44de..e79283e0a2f5 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -34,7 +34,12 @@ module Slot_id = Tezos_dal_node_services.Types.Slot_id - Add entries [None] for the slot's pages in the store, if the slot is not confirmed. *) -type Environment.Error_monad.error += Dal_invalid_page_for_slot of Dal.Page.t +type Environment.Error_monad.error += + | Dal_invalid_page_for_slot of Dal.Page.t + | Dal_attestation_status_not_final of { + published_level : int32; + slot_index : int; + } let () = let open Environment.Error_monad in @@ -49,6 +54,35 @@ let () = (function Dal_invalid_page_for_slot page_id -> Some page_id | _ -> None) (fun page_id -> Dal_invalid_page_for_slot page_id) +let () = + let open Environment.Error_monad in + register_error_kind + `Temporary + ~id:"dal_pages_request.attestation_status_not_final" + ~title:"DAL attestation status is not final" + ~description: + "The DAL attestation status for the requested slot is not final yet. We \ + cannot decide whether it is legitimate for the rollup node to import \ + it." + ~pp:(fun ppf (published_level, slot_index) -> + Format.fprintf + ppf + "DAL attestation status not final for slot %d published at level %ld. \ + We cannot decide yet if it is legitimate for the rollup node to \ + import it." + slot_index + published_level) + Data_encoding.( + obj2 + (req "published_level" Data_encoding.int32) + (req "slot_index" Data_encoding.uint8)) + (function + | Dal_attestation_status_not_final {published_level; slot_index} -> + Some (published_level, slot_index) + | _ -> None) + (fun (published_level, slot_index) -> + Dal_attestation_status_not_final {published_level; slot_index}) + module Event = struct include Internal_event.Simple @@ -193,6 +227,18 @@ let page_id_is_valid chain_id ~dal_attestation_lag ~number_of_slots slot_id ~dal_attested_slots_validity_lag +let attestation_status_not_final published_level slot_index = + let open Environment.Error_monad.Lwt_result_syntax in + let*! res = + tzfail + @@ Dal_attestation_status_not_final + { + published_level = Raw_level.to_int32 published_level; + slot_index = Sc_rollup_proto_types.Dal.Slot_index.to_octez slot_index; + } + in + Environment.wrap_tzresult res |> Lwt.return + let slot_pages (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) ~dal_activation_level ~inbox_level node_ctxt slot_id @@ -228,7 +274,8 @@ let slot_pages download_confirmed_slot_pages dal_cctxt ~published_level ~index in return (Some pages) - | `Unattested | `Waiting_attestation | `Unpublished -> return_none + | `Unattested | `Unpublished -> return_none + | `Waiting_attestation -> attestation_status_not_final published_level index let page_content (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) @@ -263,4 +310,5 @@ let page_content page_id then return_none else get_page dal_cctxt ~inbox_level page_id - | `Unattested | `Waiting_attestation | `Unpublished -> return_none + | `Unattested | `Unpublished -> return_none + | `Waiting_attestation -> attestation_status_not_final published_level index -- GitLab From cf6e3117a419de76dede81c8e3ac9f146bb0ffd9 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Fri, 24 Oct 2025 08:48:58 +0200 Subject: [PATCH 09/13] Rollups/DAL: add an error log when fetching pages data from DAL fails --- .../lib_sc_rollup_node/dal_pages_request.ml | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index e79283e0a2f5..53073d7bc852 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -116,6 +116,20 @@ module Event = struct ("inbox_level", Data_encoding.int32) ("content", Data_encoding.bytes) ~pp5:pp_content_elipsis + + let pages_reveal_failed = + declare_4 + ~section + ~name:"dal_pages_reveal_failed" + ~msg: + "Fetching pages at inbox level {inbox_level} of slot index \ + {slot_index} published at level {published_level} failed with {error}" + ~level:Error + ("inbox_level", Data_encoding.int32) + ("slot_index", Data_encoding.int31) + ("published_level", Data_encoding.int32) + ~pp4:Error_monad.pp_print_trace + ("error", Error_monad.trace_encoding) end module Slot_id_cache = @@ -239,7 +253,7 @@ let attestation_status_not_final published_level slot_index = in Environment.wrap_tzresult res |> Lwt.return -let slot_pages +let slot_pages_int (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) ~dal_activation_level ~inbox_level node_ctxt slot_id ~dal_attested_slots_validity_lag = @@ -277,7 +291,7 @@ let slot_pages | `Unattested | `Unpublished -> return_none | `Waiting_attestation -> attestation_status_not_final published_level index -let page_content +let page_content_int (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) ~dal_activation_level ~inbox_level node_ctxt ~attestation_threshold_percent:_ ~restricted_commitments_publishers:_ @@ -312,3 +326,47 @@ let page_content else get_page dal_cctxt ~inbox_level page_id | `Unattested | `Unpublished -> return_none | `Waiting_attestation -> attestation_status_not_final published_level index + +let with_errors_logging ~inbox_level slot_id f = + let open Lwt_syntax in + let* res = f in + let+ () = + match res with + | Ok _ -> return_unit + | Error err -> + Event.(emit pages_reveal_failed) + ( inbox_level, + Dal.(Slot_index.to_int slot_id.index), + Raw_level.to_int32 slot_id.published_level, + err ) + in + res + +let page_content + (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) + ~dal_activation_level ~inbox_level node_ctxt ~attestation_threshold_percent + ~restricted_commitments_publishers page_id ~dal_attested_slots_validity_lag + = + with_errors_logging ~inbox_level page_id.Dal.Page.slot_id + @@ page_content_int + dal_constants + ~dal_activation_level + ~inbox_level + node_ctxt + ~attestation_threshold_percent + ~restricted_commitments_publishers + page_id + ~dal_attested_slots_validity_lag + +let slot_pages + (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) + ~dal_activation_level ~inbox_level node_ctxt slot_id + ~dal_attested_slots_validity_lag = + with_errors_logging ~inbox_level slot_id + @@ slot_pages_int + dal_constants + ~dal_activation_level + ~inbox_level + node_ctxt + slot_id + ~dal_attested_slots_validity_lag -- GitLab From 1d1679203858187863a9d43246a3c1d5083764b4 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Thu, 23 Oct 2025 16:12:56 +0200 Subject: [PATCH 10/13] Rollups/Dal: Adapt echo/tx kernel and Arith to add some slack before fetching pages With this MR, the rollup node relies on the DAL node to fetch slots statuses and data. Since those data on the DAL node are stored once blocks are final, kernels should wait 2 levels before requesting pages. One extra level is needed to let the DAL node index the data. --- src/kernel_dal_echo/kernel/src/lib.rs | 24 +++++++++++-------- src/kernel_tx_demo/kernel/src/lib.rs | 4 +++- .../lib_protocol/sc_rollup_arith.ml | 8 ++++++- tezt/tests/dal.ml | 21 ++++++++++++++-- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/kernel_dal_echo/kernel/src/lib.rs b/src/kernel_dal_echo/kernel/src/lib.rs index 7efaee46e297..f1086996ed2c 100644 --- a/src/kernel_dal_echo/kernel/src/lib.rs +++ b/src/kernel_dal_echo/kernel/src/lib.rs @@ -99,16 +99,20 @@ pub fn entry(host: &mut impl Runtime) { match host.read_input() { Ok(Some(message)) => { let level = message.level; - let published_level = (level as i32) - (attestation_lag as i32); - let num_pages = (slot_size / page_size) as usize; - for slot_index in slot_indexes { - process_slot( - host, - published_level, - num_pages, - page_size as usize, - slot_index, - ); + // Before importing a slot, we wait 2 blocks for finality + 1 block for DAL node processing + let import_extra_delay = 3; + let published_level = (level as i32) - (attestation_lag as i32) - import_extra_delay; + if published_level > 0 { + let num_pages = (slot_size / page_size) as usize; + for slot_index in slot_indexes { + process_slot( + host, + published_level, + num_pages, + page_size as usize, + slot_index, + ); + } } } Ok(None) => { diff --git a/src/kernel_tx_demo/kernel/src/lib.rs b/src/kernel_tx_demo/kernel/src/lib.rs index 76ac692f3068..35a370356ecc 100644 --- a/src/kernel_tx_demo/kernel/src/lib.rs +++ b/src/kernel_tx_demo/kernel/src/lib.rs @@ -211,7 +211,9 @@ fn filter_inbox_message<'a, Host: Runtime>( let slot_size = 32768; let page_size = 128; let num_pages = slot_size / page_size; - let published_level = (_inbox_level - attestation_lag) as i32; + // Before importing a slot, we wait 2 blocks for finality + 1 block for DAL node processing + let import_extra_delay = 3; + let published_level = (_inbox_level - attestation_lag - import_extra_delay) as i32; // TODO: https://gitlab.com/tezos/tezos/-/issues/6400 // Make it possible to track multiple slot indexes. let slot_index = storage::dal::get_or_set_slot_index(host, 0 as u8)?; diff --git a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml index dd654b2eeee0..cd74a5390e28 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_arith.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_arith.ml @@ -1200,8 +1200,14 @@ module Make (Context : Sc_rollup_PVM_sig.Generic_pvm_context_sig) : let inbox_level = Raw_level_repr.to_int32 inbox_level in (* the [published_level]'s pages to request is [inbox_level - attestation_lag - 1]. *) + (* Before importing a slot, we wait 2 blocks for finality + 1 block + for DAL node processing, + 1 block because PVM arith requests DAL + slots at start of level internal message. *) + let import_extra_delay = 4l in let lvl = - Int32.sub (Int32.sub inbox_level dal_params.attestation_lag) 1l + Int32.sub + (Int32.sub inbox_level dal_params.attestation_lag) + import_extra_delay in match Raw_level_repr.of_int32 lvl with | Error _ -> diff --git a/tezt/tests/dal.ml b/tezt/tests/dal.ml index f6bd83e73add..64f7a7627e85 100644 --- a/tezt/tests/dal.ml +++ b/tezt/tests/dal.ml @@ -2689,6 +2689,12 @@ let test_reveal_dal_page_in_fast_exec_wasm_pvm protocol parameters dal_node Check.((Some [|true|] = dal_attestation) (option (array bool))) ~error_msg:"Unexpected DAL attestations: expected %L, got %R" ; Log.info "Wait for the rollup node to catch up to the latest level." ; + + (* Before importing a slot, we wait 2 blocks for finality + 1 block for DAL + node processing *) + let* () = bake_for ~count:3 client in + let* _level = Sc_rollup_node.wait_sync ~timeout:10. sc_rollup_node in + let* _ = Sc_rollup_node.wait_for_level ~timeout:3. sc_rollup_node level in Log.info "Read and assert against value written in durable storage." ; let key = "/output/slot-0" in @@ -7999,6 +8005,12 @@ module Tx_kernel_e2e = struct ~attestation_lag:parameters.attestation_lag ~number_of_slots:parameters.number_of_slots in + (* Before importing a slot, we wait 2 blocks for finality + 1 block for DAL + node processing. *) + let* () = bake_for client in + let* () = bake_for client in + let* () = bake_for client in + Log.info "Wait for the rollup node to catch up." ; let* current_level = Node.get_level node in let* _level = @@ -8069,9 +8081,14 @@ module Tx_kernel_e2e = struct ~attestation_lag:parameters.attestation_lag ~number_of_slots:parameters.number_of_slots in - Log.info "Wait for the rollup node to catch up." ; + + (* Before importing a slot, we wait 2 blocks for finality + 1 block for DAL + node processing *) + let* () = repeat 3 (fun () -> bake_for client) in + let* _level = Sc_rollup_node.wait_sync ~timeout:10. sc_rollup_node in + Log.info "Wait for the rollup node to catch up at level %d." target_level ; let* _level = - Sc_rollup_node.wait_for_level ~timeout:30. sc_rollup_node target_level + Sc_rollup_node.wait_for_level ~timeout:60. sc_rollup_node target_level in let key = "/output/slot-0" in let* value_written = -- GitLab From c3e17458451e7d4593cc41957cac42b30e99fa24 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Fri, 24 Oct 2025 17:25:00 +0200 Subject: [PATCH 11/13] Rollups/DAL: remove adaptive DAL related parameters and update the doc-strings --- .../lib_sc_rollup_node/dal_pages_request.ml | 12 +-- .../lib_sc_rollup_node/dal_pages_request.mli | 75 +++++++------------ .../lib_sc_rollup_node/fueled_pvm.ml | 36 ++------- 3 files changed, 36 insertions(+), 87 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index 53073d7bc852..25ffcf348fe3 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -293,9 +293,8 @@ let slot_pages_int let page_content_int (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) - ~dal_activation_level ~inbox_level node_ctxt - ~attestation_threshold_percent:_ ~restricted_commitments_publishers:_ - page_id ~dal_attested_slots_validity_lag = + ~dal_activation_level ~inbox_level node_ctxt page_id + ~dal_attested_slots_validity_lag = let open Lwt_result_syntax in let Node_context.{genesis_info = {level = origination_level; _}; l1_ctxt; _} = node_ctxt @@ -344,17 +343,14 @@ let with_errors_logging ~inbox_level slot_id f = let page_content (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) - ~dal_activation_level ~inbox_level node_ctxt ~attestation_threshold_percent - ~restricted_commitments_publishers page_id ~dal_attested_slots_validity_lag - = + ~dal_activation_level ~inbox_level node_ctxt page_id + ~dal_attested_slots_validity_lag = with_errors_logging ~inbox_level page_id.Dal.Page.slot_id @@ page_content_int dal_constants ~dal_activation_level ~inbox_level node_ctxt - ~attestation_threshold_percent - ~restricted_commitments_publishers page_id ~dal_attested_slots_validity_lag diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.mli b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.mli index f52b2cc3b987..18b1b9abd5ef 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.mli +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.mli @@ -30,29 +30,30 @@ open Alpha_context Rework the interface of dal_pages_request.mli (see the issue for details). *) -(** Access DAL slots and pages content. - - This module is a wrapper on top of {!Store.Dal_slot_pages} module to - access DAL slots and pages' data that have been previously fetched by - the rollup node. -*) - -(** Retrieve the pages' content of the given slot ID's from the store. - - The function returns [Dal_slot_not_found_in_store] if no entry is found in - the store for the given ID (i.e. no page is registered with or without content). - - If the returned value is [Some pages], the slot whose ID is given is - supposed to be confirmed and [pages] correspond to the pages of the slot. - Otherwise [None] is returned. - - The function relies on {!Store.Dal_slot_pages}'s invariants to guarantee that: - - the pages are returned in increasing order w.r.t. their indexes in the slot; - - the size of the list, in case it is not empty, is equal to the expected - number of pages in a slot. - - [dal_attestation_lag] is used to retrieve the correct entry in [store]. -*) +(** Access DAL slots and page contents. + + This module exposes helpers to retrieve DAL slot/page data for a rollup, + validating import conditions against the DAL attestation lag and the + rollup's context. It queries a DAL node to obtain the slot status and, when + appropriate, to download page contents. *) + +(** Retrieve the pages of the given slot. + + The function queries the DAL node for the slot's attestation status: + - If the slot is [Attested lag], the function checks that importing the slot + at [inbox_level] is valid given: + - the DAL activation level, + - the rollup origination level, + - the attested slots validity lag, and + - index bounds (number of slots). + If valid, it downloads and returns [Some pages]; otherwise returns [None]. + - If the slot is [Unattested] or [Unpublished], returns [None]. + - If the status is [Waiting_attestation], the function returns an error + ([Dal_attestation_status_not_final]). + + The returned pages, when present, satisfy: + - pages are ordered by increasing page index within the slot, + - the list length equals the expected number of pages for the slot. *) val slot_pages : Octez_smart_rollup.Rollup_constants.dal_constants -> dal_activation_level:Raw_level.t option -> @@ -62,38 +63,14 @@ val slot_pages : dal_attested_slots_validity_lag:int -> Dal.Page.content list option tzresult Lwt.t -(** Retrieve the content of the page identified by the given ID from the store. - - This function checks the attestation status of the page's slot by inspecting - the skip list cells stored on L1 at the slot's attested level. A slot is - considered attested if either one of the following conditions is met: - - - The [is_proto_attested] field in the content of the cell is true, and - attestation_threshold_percent is None (default DAL behavior). - - - The attestation_threshold_percent is set to a specific threshold, the slot - meets or exceeds this threshold, and the publisher is authorized, provided a - whitelist is specified in [restricted_commitments_publishers]. - - If the slot of the page is attested, the data is retrieved from the DAL node - and returned. Otherwise, the function returns None. It also returns None if - the page_id or slot_id is invalid (or no longer valid). This includes cases - where: - - - Indices are out of range. - - - The rollup was originated after the slot's publication. +(** Retrieve the content of a single page. - - The slot is too old (i.e., its level is beyond - [dal_attested_slots_validity_lag]). -*) + Same as {!slot_pages}, but for a single page. *) val page_content : Octez_smart_rollup.Rollup_constants.dal_constants -> dal_activation_level:Raw_level.t option -> inbox_level:int32 -> _ Node_context.t -> - attestation_threshold_percent:int option -> - restricted_commitments_publishers:Contract.t list option -> Dal.Page.t -> dal_attested_slots_validity_lag:int -> Dal.Page.content option tzresult Lwt.t diff --git a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml index 4ddc7d5713d1..a972ac758266 100644 --- a/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml +++ b/src/proto_alpha/lib_sc_rollup_node/fueled_pvm.ml @@ -141,20 +141,10 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct Sc_rollup.Metadata.encoding metadata) | (Request_dal_page _ | Request_adal_page _) as xdal_request -> ( - let ( dal_page, - attestation_threshold_percent, - restricted_commitments_publishers ) = + let dal_page = match xdal_request with - | Request_dal_page dal_page -> (dal_page, None, None) - | Request_adal_page - { - page_id; - attestation_threshold_percent; - restricted_commitments_publishers; - } -> - ( page_id, - Some attestation_threshold_percent, - restricted_commitments_publishers ) + | Request_dal_page dal_page -> dal_page + | Request_adal_page _ -> Stdlib.failwith "Not_implemented" | _ -> (* This case is not reachable because we know that [xdal_request] is either [Request_dal_page] or [Request_adal_page] *) @@ -167,8 +157,6 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct ~dal_attested_slots_validity_lag ~inbox_level:(Int32.of_int level) node_ctxt - ~attestation_threshold_percent - ~restricted_commitments_publishers dal_page in match content with @@ -308,20 +296,10 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct go fuel (Int64.succ current_tick) failing_ticks state) | Needs_reveal ((Request_dal_page _ | Request_adal_page _) as xdal_request) -> ( - let ( page_id, - attestation_threshold_percent, - restricted_commitments_publishers ) = + let page_id = match xdal_request with - | Request_dal_page page_id -> (page_id, None, None) - | Request_adal_page - { - page_id; - attestation_threshold_percent; - restricted_commitments_publishers; - } -> - ( page_id, - Some attestation_threshold_percent, - restricted_commitments_publishers ) + | Request_dal_page page_id -> page_id + | Request_adal_page _ -> Stdlib.failwith "Not_implemented" | _ -> (* This case is not reachable because we know that [xdal_request] is either [Request_dal_page] or [Request_adal_page] *) @@ -337,8 +315,6 @@ module Make_fueled (F : Fuel.S) : FUELED_PVM with type fuel = F.t = struct ~dal_activation_level ~dal_attested_slots_validity_lag node_ctxt - ~attestation_threshold_percent - ~restricted_commitments_publishers page_id in let*! () = -- GitLab From 1c631c7d29cd14729f9f9226449b738d38b7eca2 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Tue, 28 Oct 2025 14:49:39 +0100 Subject: [PATCH 12/13] Rollups/DAL: documents cache sizes' values --- .../lib_sc_rollup_node/dal_pages_request.ml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index 25ffcf348fe3..0d4b8cfd33e4 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -137,7 +137,12 @@ module Slot_id_cache = let download_confirmed_slot_pages = let open Lwt_result_syntax in - let cache = Slot_id_cache.create 32 in + (* The size below was chosen arbitrarily, but it should be sufficient for + Etherlink, given that slots are pulled and processed in some order and only + once. In general a kernel may request data it previously processed during + normal operation (i.e., not for refutation games). This size can then be + adapted as needed. *) + let cache = Slot_id_cache.create 16 in fun dal_cctxt ~published_level ~index -> let slot_id = Slot_id. @@ -153,7 +158,12 @@ let download_confirmed_slot_pages = (* Adaptive DAL is not supported anymore *) let get_slot_header_attestation_info = let open Lwt_result_syntax in - let cache = Slot_id_cache.create 160 in + (* The size was chosen arbitrarily, but it should be sufficient for Etherlink, + given that slots statuses are pulled and processed in some order and only + once. In general a kernel may request data it previously processed during + normal operation (i.e., not for refutation games). This size can then be + adapted as needed. *) + let cache = Slot_id_cache.create 16 in fun dal_cctxt ~published_level ~index -> let slot_id = Slot_id. -- GitLab From 6e245dfe8aafc11874b0a5642eba9981c96b70c8 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Fri, 7 Nov 2025 09:07:46 +0100 Subject: [PATCH 13/13] Rollups/DAL: correctly fail if DAL pages are requested but no DAL node is given --- .../lib_sc_rollup_node/dal_pages_request.ml | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml index 0d4b8cfd33e4..888a1298e2d3 100644 --- a/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml +++ b/src/proto_alpha/lib_sc_rollup_node/dal_pages_request.ml @@ -35,6 +35,7 @@ module Slot_id = Tezos_dal_node_services.Types.Slot_id is not confirmed. *) type Environment.Error_monad.error += + | No_dal_node_provided | Dal_invalid_page_for_slot of Dal.Page.t | Dal_attestation_status_not_final of { published_level : int32; @@ -83,6 +84,19 @@ let () = (fun (published_level, slot_index) -> Dal_attestation_status_not_final {published_level; slot_index}) +let () = + let open Environment.Error_monad in + register_error_kind + `Permanent + ~id:"dal_pages_request.no_dal_node_provided" + ~title:"No DAL node provided" + ~description:"No DAL node was provided" + ~pp:(fun ppf () -> + Format.fprintf ppf "No DAL node provided to fetch slot pages.") + Data_encoding.unit + (function No_dal_node_provided -> Some () | _ -> None) + (fun () -> No_dal_node_provided) + module Event = struct include Internal_event.Simple @@ -263,6 +277,14 @@ let attestation_status_not_final published_level slot_index = in Environment.wrap_tzresult res |> Lwt.return +let get_dal_node cctxt_opt = + let open Environment.Error_monad.Lwt_result_syntax in + match cctxt_opt with + | Some res -> return res + | None -> + let*! err = tzfail No_dal_node_provided in + Environment.wrap_tzresult err |> Lwt.return + let slot_pages_int (dal_constants : Octez_smart_rollup.Rollup_constants.dal_constants) ~dal_activation_level ~inbox_level node_ctxt slot_id @@ -272,8 +294,7 @@ let slot_pages_int node_ctxt in let* chain_id = Layer1.get_chain_id l1_ctxt in - (* DAL must be configured for this point to be reached *) - let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ node_ctxt.dal_cctxt in + let* dal_cctxt = get_dal_node node_ctxt.dal_cctxt in let Dal.Slot.Header.{published_level; index} = slot_id in let* status = get_slot_header_attestation_info dal_cctxt ~published_level ~index @@ -310,8 +331,7 @@ let page_content_int node_ctxt in let* chain_id = Layer1.get_chain_id l1_ctxt in - (* DAL must be configured for this point to be reached *) - let dal_cctxt = WithExceptions.Option.get ~loc:__LOC__ node_ctxt.dal_cctxt in + let* dal_cctxt = get_dal_node node_ctxt.dal_cctxt in let Dal.Slot.Header.{published_level; index} = page_id.Dal.Page.slot_id in let* status = get_slot_header_attestation_info dal_cctxt ~published_level ~index -- GitLab