From 868d8eea2440fe9b02c2f2308fbccc6b317fc174 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 8 Oct 2025 08:57:12 +0200 Subject: [PATCH 1/4] DAL/Proto: verify_proof returns the attestation_lag in the target SL cell --- src/proto_alpha/lib_protocol/dal_slot_repr.ml | 52 +++++++++++-------- .../lib_protocol/dal_slot_repr.mli | 12 ++++- .../lib_protocol/sc_rollup_proof_repr.ml | 4 +- .../lib_protocol/test/helpers/dal_helpers.ml | 1 + 4 files changed, 44 insertions(+), 25 deletions(-) diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 4103c567e44b..2e674b521282 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -1545,15 +1545,17 @@ module History = struct let cell_content = Skip_list.content target_cell in (* We check that the target cell has the same level and index than the page we're about to prove. *) - let cell_id = (Content.content_id cell_content).header_id in + let {header_id = slot_id; attestation_lag} = + Content.content_id cell_content + in let* () = error_when - Raw_level_repr.(cell_id.published_level <> published_level) + Raw_level_repr.(slot_id.published_level <> published_level) (dal_proof_error "verify_proof_repr: published_level mismatch.") in let* () = error_when - (not (Dal_slot_index_repr.equal cell_id.index index)) + (not (Dal_slot_index_repr.equal slot_id.index index)) (dal_proof_error "verify_proof_repr: slot index mismatch.") in (* We check that the given inclusion proof indeed links our L1 snapshot to @@ -1567,25 +1569,33 @@ module History = struct ~restricted_commitments_publishers cell_content in - match (proof, is_commitment_attested) with - | Page_unconfirmed _, Some _ -> - error - @@ dal_proof_error - "verify_proof_repr: the confirmation proof doesn't contain the \ - attested slot." - | Page_unconfirmed _, None -> return_none - | Page_confirmed _, None -> - error - @@ dal_proof_error - "verify_proof_repr: the unconfirmation proof contains the \ - target slot." - | Page_confirmed {page_data; page_proof; _}, Some commitment -> - (* We check that the page indeed belongs to the target slot at the + let* data_opt = + match (proof, is_commitment_attested) with + | Page_unconfirmed _, Some _ -> + error + @@ dal_proof_error + "verify_proof_repr: the confirmation proof doesn't contain \ + the attested slot." + | Page_unconfirmed _, None -> return_none + | Page_confirmed _, None -> + error + @@ dal_proof_error + "verify_proof_repr: the unconfirmation proof contains the \ + target slot." + | Page_confirmed {page_data; page_proof; _}, Some commitment -> + (* We check that the page indeed belongs to the target slot at the given page index. *) - let* () = - check_page_proof dal_params page_proof page_data page_id commitment - in - return_some page_data + let* () = + check_page_proof + dal_params + page_proof + page_data + page_id + commitment + in + return_some page_data + in + return (data_opt, attestation_lag) let verify_proof dal_params page_id snapshot serialized_proof = let open Result_syntax in diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index 6e9d30c457b2..d1ec1c808e74 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -520,8 +520,16 @@ module History : sig that could contain the page identified by [page_id]. [dal_parameters] is used when verifying that/if the page is part of - the candidate slot (if any). *) - val verify_proof : parameters -> Page.t -> t -> proof -> bytes option tzresult + the candidate slot (if any). + + In both cases, the attestation lag used for the target cell in the skip + list is returned, alongside the page's bytes if the slot is attested. *) + val verify_proof : + parameters -> + Page.t -> + t -> + proof -> + (bytes option * attestation_lag_kind) tzresult (** Given a DAL proof, this function returns the values of the fields [attestation_threshold_percent] [restricted_commitments_publishers] stored diff --git a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml index 6348484c6825..4d0b515c532b 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml @@ -304,14 +304,14 @@ module Dal_helpers = struct page_id ~dal_attested_slots_validity_lag then - let* input = + let* input_opt, _attestation_lag = Dal_slot_repr.History.verify_proof dal_parameters page_id dal_snapshot proof in - return_some (Sc_rollup_PVM_sig.Reveal (Dal_page input)) + return_some (Sc_rollup_PVM_sig.Reveal (Dal_page input_opt)) else return_none let produce ~metadata ~dal_activation_level ~dal_attestation_lag 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 f516f1987bf8..7493b67bb6c5 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml @@ -217,6 +217,7 @@ struct | Some check_verify -> let*? proof, _input_opt = res in let@ res = Hist.verify_proof params page_id skip_list proof in + let res = Result.map (fun (bytes_opt, _lag) -> bytes_opt) res in check_verify res page_info (* Some check functions. *) -- GitLab From 5c6558b1cc4d14a5214623d06193c17c6ca2f142 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 8 Oct 2025 08:59:47 +0200 Subject: [PATCH 2/4] DAL/Proto: sc_rollup_proof uses the lag from the skip list to verify proofs The attestation_lag fetched from the context is not used anymore --- .../lib_protocol/sc_rollup_proof_repr.ml | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml index 4d0b515c532b..12d4733c2641 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml @@ -289,10 +289,20 @@ module Dal_helpers = struct ~published_level ~dal_attested_slots_validity_lag - let verify ~metadata ~dal_activation_level ~dal_attestation_lag - ~dal_number_of_slots ~commit_inbox_level dal_parameters page_id - dal_snapshot proof ~dal_attested_slots_validity_lag = + let verify ~metadata ~dal_activation_level ~dal_number_of_slots + ~commit_inbox_level dal_parameters page_id dal_snapshot proof + ~dal_attested_slots_validity_lag = let open Result_syntax in + let* input_opt, attestation_lag = + Dal_slot_repr.History.verify_proof + dal_parameters + page_id + dal_snapshot + proof + in + let dal_attestation_lag = + Dal_slot_repr.History.attestation_lag_value attestation_lag + in if page_id_is_valid dal_parameters @@ -303,15 +313,7 @@ module Dal_helpers = struct ~dal_number_of_slots page_id ~dal_attested_slots_validity_lag - then - let* input_opt, _attestation_lag = - Dal_slot_repr.History.verify_proof - dal_parameters - page_id - dal_snapshot - proof - in - return_some (Sc_rollup_PVM_sig.Reveal (Dal_page input_opt)) + then return_some (Sc_rollup_PVM_sig.Reveal (Dal_page input_opt)) else return_none let produce ~metadata ~dal_activation_level ~dal_attestation_lag @@ -414,7 +416,6 @@ let valid (type state proof output) ~dal_activation_level ~dal_attested_slots_validity_lag dal_parameters - ~dal_attestation_lag ~commit_inbox_level page_id dal_snapshot -- GitLab From 81406ad16f3b638c7f456de10ea6963bbc45f39a Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 8 Oct 2025 10:52:08 +0200 Subject: [PATCH 3/4] DAL/Proto: produce_proof returns the attestation_lag in the target SL cell --- src/proto_alpha/lib_protocol/dal_slot_repr.ml | 123 +++++++++--------- .../lib_protocol/dal_slot_repr.mli | 8 +- .../lib_protocol/sc_rollup_proof_repr.ml | 2 +- .../lib_protocol/test/helpers/dal_helpers.ml | 3 + 4 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 2e674b521282..f5b0ee753607 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -1403,73 +1403,80 @@ module History = struct @@ dal_proof_error "Skip_list.search returned Nearest', while all given levels to \ produce proofs are supposed to be in the skip list." - | Found target_cell -> ( - let inc_proof = List.rev search_result.Skip_list.rev_path in - let is_commitment_attested = - Skip_list.content target_cell - |> is_commitment_attested - ~attestation_threshold_percent - ~restricted_commitments_publishers - in - match (page_info, is_commitment_attested) with - | Some (page_data, page_proof), Some commitment -> - (* The case where the slot to which the page is supposed to belong + | Found target_cell -> + let* proof, page_opt = + let inc_proof = List.rev search_result.Skip_list.rev_path in + let is_commitment_attested = + Skip_list.content target_cell + |> is_commitment_attested + ~attestation_threshold_percent + ~restricted_commitments_publishers + in + match (page_info, is_commitment_attested) with + | Some (page_data, page_proof), Some commitment -> + (* The case where the slot to which the page is supposed to belong is found and the page's information are given. *) - let*? () = - (* We check the page's proof against the commitment. *) - check_page_proof - dal_params - page_proof - page_data - page_id - commitment - in - (* All checks succeeded. We return a `Page_confirmed` proof. *) - return - ( Page_confirmed - { - target_cell; - inc_proof; - page_data; - page_proof; - attestation_threshold_percent; - restricted_commitments_publishers; - }, - Some page_data ) - | None, None -> - (* The slot corresponding to the given page's index is not found in + let*? () = + (* We check the page's proof against the commitment. *) + check_page_proof + dal_params + page_proof + page_data + page_id + commitment + in + (* All checks succeeded. We return a `Page_confirmed` proof. *) + return + ( Page_confirmed + { + target_cell; + inc_proof; + page_data; + page_proof; + attestation_threshold_percent; + restricted_commitments_publishers; + }, + Some page_data ) + | None, None -> + (* The slot corresponding to the given page's index is not found in the attested slots of the page's level, and no information is given for that page. So, we produce a proof that the page is not attested. *) - return - ( Page_unconfirmed - { - target_cell; - inc_proof; - attestation_threshold_percent; - restricted_commitments_publishers; - }, - None ) - | None, Some _ -> - (* Mismatch: case where no page information are given, but the + return + ( Page_unconfirmed + { + target_cell; + inc_proof; + attestation_threshold_percent; + restricted_commitments_publishers; + }, + None ) + | None, Some _ -> + (* Mismatch: case where no page information are given, but the slot is attested. *) - tzfail - @@ dal_proof_error - "The page ID's slot is confirmed, but no page content and \ - proof are provided." - | Some _, None -> - (* Mismatch: case where page information are given, but the slot + tzfail + @@ dal_proof_error + "The page ID's slot is confirmed, but no page content and \ + proof are provided." + | Some _, None -> + (* Mismatch: case where page information are given, but the slot is not attested. *) - tzfail - @@ dal_proof_error - "The page ID's slot is not confirmed, but page content and \ - proof are provided.") + tzfail + @@ dal_proof_error + "The page ID's slot is not confirmed, but page content \ + and proof are provided." + in + let {attestation_lag; header_id = _} = + Skip_list.content target_cell |> Content.content_id + in + return (proof, page_opt, attestation_lag) let produce_proof dal_params ~attestation_threshold_percent ~restricted_commitments_publishers page_id ~page_info ~get_history - slots_hist : (proof * Page.content option) tzresult Lwt.t = + slots_hist : + (proof * Page.content option * attestation_lag_kind) tzresult Lwt.t = let open Lwt_result_syntax in - let* proof_repr, page_data = + let* proof_repr, page_data, attestation_lag = produce_proof_repr dal_params ~attestation_threshold_percent @@ -1480,7 +1487,7 @@ module History = struct slots_hist in let*? serialized_proof = serialize_proof proof_repr in - return (serialized_proof, page_data) + return (serialized_proof, page_data, attestation_lag) (* Given a starting cell [snapshot] and a (final) [target], this function checks that the provided [inc_proof] encodes a minimal path from diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index d1ec1c808e74..47ca00b86b38 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -499,7 +499,11 @@ module History : sig attestation threshold of the commitment is used instead of the Protocol's flag to decide if the page's slot is attested. Furthermore, in case some publishers are provided in [restricted_commitments_publishers], we also - check if the commitment's publisher is whitelisted in that list. *) + check if the commitment's publisher is whitelisted in that list. + + The returned result also contains the attestation lag used for the target + cell in the skip list so that refutation games use the correct value, + in particular across protocol migrations that decrease the lag. *) val produce_proof : parameters -> attestation_threshold_percent:int option -> @@ -508,7 +512,7 @@ module History : sig page_info:(Page.content * Page.proof) option -> get_history:(hash -> t option Lwt.t) -> t -> - (proof * Page.content option) tzresult Lwt.t + (proof * Page.content option * attestation_lag_kind) tzresult Lwt.t (** [verify_proof dal_params page_id snapshot proof] verifies that the given [proof] is a valid proof to show that either: diff --git a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml index 12d4733c2641..8e662eb0c36d 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml @@ -333,7 +333,7 @@ module Dal_helpers = struct page_id ~dal_attested_slots_validity_lag then - let* proof, content_opt = + let* proof, content_opt, _attestation_lag = Dal_slot_repr.History.produce_proof dal_parameters ~attestation_threshold_percent 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 7493b67bb6c5..ea8af07713a9 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/dal_helpers.ml @@ -211,6 +211,9 @@ struct ~get_history skip_list in + let res = + Result.map (fun (proof, input_opt, _lag) -> (proof, input_opt)) res + in let* () = check_produce res page_info in match check_verify with | None -> return_unit -- GitLab From 2a40db3167b45868cb166aeeaafd9e57052153b3 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 8 Oct 2025 10:54:48 +0200 Subject: [PATCH 4/4] DAL/Proto: sc_rollup_proof uses the lag from the skip list to produce proofs The attestation_lag given by the rollup node is not used anymore to produce proofs --- .../lib_protocol/sc_rollup_proof_repr.ml | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml index 8e662eb0c36d..49b4130e1329 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_proof_repr.ml @@ -316,12 +316,24 @@ module Dal_helpers = struct then return_some (Sc_rollup_PVM_sig.Reveal (Dal_page input_opt)) else return_none - let produce ~metadata ~dal_activation_level ~dal_attestation_lag - ~dal_number_of_slots ~commit_inbox_level dal_parameters - ~attestation_threshold_percent ~restricted_commitments_publishers page_id - ~page_info ~get_history confirmed_slots_history - ~dal_attested_slots_validity_lag = + let produce ~metadata ~dal_activation_level ~dal_number_of_slots + ~commit_inbox_level dal_parameters ~attestation_threshold_percent + ~restricted_commitments_publishers page_id ~page_info ~get_history + confirmed_slots_history ~dal_attested_slots_validity_lag = let open Lwt_result_syntax in + let* proof, content_opt, attestation_lag = + Dal_slot_repr.History.produce_proof + dal_parameters + ~attestation_threshold_percent + ~restricted_commitments_publishers + page_id + ~page_info + ~get_history + confirmed_slots_history + in + let dal_attestation_lag = + Dal_slot_repr.History.attestation_lag_value attestation_lag + in if page_id_is_valid dal_parameters @@ -333,16 +345,6 @@ module Dal_helpers = struct page_id ~dal_attested_slots_validity_lag then - let* proof, content_opt, _attestation_lag = - Dal_slot_repr.History.produce_proof - dal_parameters - ~attestation_threshold_percent - ~restricted_commitments_publishers - page_id - ~page_info - ~get_history - confirmed_slots_history - in return ( Some (Reveal_proof (Dal_page_proof {proof; page_id})), Some (Sc_rollup_PVM_sig.Reveal (Dal_page content_opt)) ) @@ -612,7 +614,6 @@ let produce ~metadata pvm_and_state commit_inbox_level ~is_reveal_enabled = ~metadata ~dal_activation_level dal_parameters - ~dal_attestation_lag ~commit_inbox_level ~attestation_threshold_percent:None ~restricted_commitments_publishers:None @@ -637,7 +638,6 @@ let produce ~metadata pvm_and_state commit_inbox_level ~is_reveal_enabled = ~metadata ~dal_activation_level dal_parameters - ~dal_attestation_lag ~commit_inbox_level ~attestation_threshold_percent ~restricted_commitments_publishers -- GitLab