From 3369cc7cf823b7ada55f77d75e81358d98c2540c Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Mon, 21 Oct 2024 09:10:23 +0200 Subject: [PATCH 1/6] DAL/Proto: propagete the tz address that publishes a DAL commitment until dal_slot_repr For the moment, the source is not used at all, but this will be done in the next commits --- .../lib_benchmarks_proto/dal_benchmarks.ml | 7 ++++++- src/proto_alpha/lib_protocol/alpha_context.mli | 3 ++- src/proto_alpha/lib_protocol/apply.ml | 2 +- src/proto_alpha/lib_protocol/dal_apply.ml | 4 ++-- src/proto_alpha/lib_protocol/dal_apply.mli | 11 +++++++---- src/proto_alpha/lib_protocol/dal_slot_repr.ml | 4 +++- src/proto_alpha/lib_protocol/dal_slot_repr.mli | 14 ++++++++------ src/proto_alpha/lib_protocol/raw_context.ml | 3 ++- src/proto_alpha/lib_protocol/raw_context.mli | 17 ++++++++++------- 9 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/proto_alpha/lib_benchmarks_proto/dal_benchmarks.ml b/src/proto_alpha/lib_benchmarks_proto/dal_benchmarks.ml index 82a1f5aa6a99..8e2f3b535e2f 100644 --- a/src/proto_alpha/lib_benchmarks_proto/dal_benchmarks.ml +++ b/src/proto_alpha/lib_benchmarks_proto/dal_benchmarks.ml @@ -107,7 +107,12 @@ module Publish_commitment : Benchmark.S = struct in let workload = () in let closure () = - match Dal_apply.apply_publish_commitment ctxt op with + match + Dal_apply.apply_publish_commitment + ctxt + op + ~source:Environment.Signature.Public_key_hash.zero + with | Error errs -> Format.eprintf "%a@." Environment.Error_monad.pp_trace errs ; Stdlib.failwith diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index eb0311381e2d..2b0a038666cc 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2871,7 +2871,8 @@ module Dal : sig val equal : t -> t -> bool end - val register_slot_header : context -> Header.t -> context tzresult + val register_slot_header : + context -> Header.t -> source:public_key_hash -> context tzresult val find_slot_headers : context -> Raw_level.t -> Header.t list option tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 94b9f3172fbb..939399085882 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -1438,7 +1438,7 @@ let apply_manager_operation : [] ) | Dal_publish_commitment slot_header -> let*? ctxt, slot_header = - Dal_apply.apply_publish_commitment ctxt slot_header + Dal_apply.apply_publish_commitment ctxt slot_header ~source in let consumed_gas = Gas.consumed ~since:ctxt_before_op ~until:ctxt in let result = diff --git a/src/proto_alpha/lib_protocol/dal_apply.ml b/src/proto_alpha/lib_protocol/dal_apply.ml index c3c5b1aa16fc..b79a4819a254 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.ml +++ b/src/proto_alpha/lib_protocol/dal_apply.ml @@ -87,7 +87,7 @@ let apply_attestation ctxt attestation ~power = let validate_publish_commitment ctxt _operation = assert_dal_feature_enabled ctxt -let apply_publish_commitment ctxt operation = +let apply_publish_commitment ctxt operation ~source = let open Result_syntax in let* ctxt = Gas.consume ctxt Dal_costs.cost_Dal_publish_commitment in let number_of_slots = Dal.number_of_slots ctxt in @@ -100,7 +100,7 @@ let apply_publish_commitment ctxt operation = ~current_level operation in - let* ctxt = Dal.Slot.register_slot_header ctxt slot_header in + let* ctxt = Dal.Slot.register_slot_header ctxt slot_header ~source in return (ctxt, slot_header) let finalisation ctxt = diff --git a/src/proto_alpha/lib_protocol/dal_apply.mli b/src/proto_alpha/lib_protocol/dal_apply.mli index 55bd78051f1a..138e9b998214 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.mli +++ b/src/proto_alpha/lib_protocol/dal_apply.mli @@ -57,11 +57,14 @@ val apply_attestation : t -> Dal.Attestation.t -> power:int -> t tzresult val validate_publish_commitment : t -> Dal.Operations.Publish_commitment.t -> unit tzresult -(** [apply_publish_commitment ctxt slot_header] applies the publication of - slot header [slot_header] on top of [ctxt]. Fails if the slot contains - already a slot header. *) +(** [apply_publish_commitment ctxt slot_header ~source] applies the publication + of slot header [slot_header] signed by [source] on top of [ctxt]. Fails if + the slot already contains a slot header. *) val apply_publish_commitment : - t -> Dal.Operations.Publish_commitment.t -> (t * Dal.Slot.Header.t) tzresult + t -> + Dal.Operations.Publish_commitment.t -> + source:public_key_hash -> + (t * Dal.Slot.Header.t) tzresult (** [finalisation ctxt] should be executed at block finalisation time. A set of slots attested at level [ctxt.current_level - lag] diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 87fc6d51ab7e..895a781ef982 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -228,8 +228,10 @@ module Slot_market = struct let length {length; _} = length - let register t new_slot_header = + let register t new_slot_header ~source = let open Header in + (* WIP: This will be used in the next commits. *) + ignore source ; if not Compare.Int.( diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index 568e27b34844..9834f6dcfc43 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -187,12 +187,14 @@ module Slot_market : sig (see {!val:init}). *) val length : t -> int - (** [register t index fees] updates the candidate associated to - index [index]. Returns [Some (_, true)] if the candidate is - registered. Returns [Some (_, false)] otherwise. Returns [None] - if the [index] is not in the interval [0;length] where [length] - is the value provided to the [init] function. *) - val register : t -> Header.t -> (t * bool) option + (** [register t slot_header ~source] possibly updates the candidate associated + to [slot_header.id] with the [slot_header] published by [source]. + + The function returns [Some (_, true)] if the candidate is + registered. Returns [Some (_, false)] otherwise. Returns [None] if + [slot_header.id] is not a valid slot id. *) + val register : + t -> Header.t -> source:Signature.public_key_hash -> (t * bool) option (** [candidates t] returns a list of slot header candidates. *) val candidates : t -> Header.t list diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index fa494e315d3e..2abb8a55ff97 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -2144,12 +2144,13 @@ module Dal = struct in {ctxt with back = {ctxt.back with dal_attestation_slot_accountability}} - let register_slot_header ctxt slot_header = + let register_slot_header ctxt slot_header ~source = let open Result_syntax in match Dal_slot_repr.Slot_market.register ctxt.back.dal_slot_fee_market slot_header + ~source with | None -> let length = diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index d9de5caa5341..ae56f129cfe6 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -441,13 +441,16 @@ module Dal : sig available by some attester). *) val record_number_of_attested_shards : t -> Dal_attestation_repr.t -> int -> t - (** [register_slot_header ctxt slot_header] returns a new context - where the new candidate [slot] have been taken into - account. Returns [Some (ctxt,updated)] where [updated=true] if - the candidate is registered. [Some (ctxt,false)] if another - candidate was already registered previously. Returns an error if - the slot is invalid. *) - val register_slot_header : t -> Dal_slot_repr.Header.t -> t tzresult + (** [register_slot_header ctxt slot_header ~source] returns a new context + where the new candidate [slot] published by [source] has been taken into + account. Returns [Some (ctxt,updated)] where [updated=true] if the + candidate is registered. [Some (ctxt,false)] if another candidate was + already registered previously. Returns an error if the slot is invalid. *) + val register_slot_header : + t -> + Dal_slot_repr.Header.t -> + source:Signature.public_key_hash -> + t tzresult (** [candidates ctxt] returns the current list of slot for which there is at least one candidate. *) -- GitLab From 99239b7e51dbe802e614f828f9f69d5c156fb2a5 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Mon, 21 Oct 2024 09:20:27 +0200 Subject: [PATCH 2/6] DAL/Proto: remember DAL commitments publishers until the slots info are saved into the context In the next commits, we'll handle saving the addresses into the storage, but this will require q kind of migration, as the format/encoding will will change --- src/proto_alpha/lib_protocol/dal_slot_repr.ml | 9 +++++---- src/proto_alpha/lib_protocol/dal_slot_repr.mli | 5 +++-- src/proto_alpha/lib_protocol/dal_slot_storage.ml | 4 +++- src/proto_alpha/lib_protocol/raw_context.mli | 7 ++++--- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 895a781ef982..1f168e3db3d1 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -218,7 +218,10 @@ module Slot_market = struct module Slot_index_map = Map.Make (Dal_slot_index_repr) - type t = {length : int; slot_headers : Header.t Slot_index_map.t} + type t = { + length : int; + slot_headers : (Header.t * Signature.public_key_hash) Slot_index_map.t; + } let init ~length = if Compare.Int.(length < 0) then @@ -230,8 +233,6 @@ module Slot_market = struct let register t new_slot_header ~source = let open Header in - (* WIP: This will be used in the next commits. *) - ignore source ; if not Compare.Int.( @@ -243,7 +244,7 @@ module Slot_market = struct let update = function | None -> has_changed := true ; - Some new_slot_header + Some (new_slot_header, source) | Some x -> Some x in let slot_headers = diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index 9834f6dcfc43..c73efb3b8c52 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -196,8 +196,9 @@ module Slot_market : sig val register : t -> Header.t -> source:Signature.public_key_hash -> (t * bool) option - (** [candidates t] returns a list of slot header candidates. *) - val candidates : t -> Header.t list + (** [candidates t] returns a list of slot header candidates associated to the + public key hashes of the managers who published them. *) + val candidates : t -> (Header.t * Signature.public_key_hash) list end (** This module provides an abstract data structure (type {!History.t}) that diff --git a/src/proto_alpha/lib_protocol/dal_slot_storage.ml b/src/proto_alpha/lib_protocol/dal_slot_storage.ml index a5f8621c6bf4..b59e2166d6f2 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_storage.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_storage.ml @@ -31,7 +31,9 @@ let finalize_current_slot_headers ctxt = Storage.Dal.Slot.Headers.add ctxt (Raw_context.current_level ctxt).level - (Raw_context.Dal.candidates ctxt) + (* WIP: The correct handling of addresses associated to commitments will be + done in the next commits. *) + (Raw_context.Dal.candidates ctxt |> List.map fst) let compute_slot_headers_statuses ~is_slot_attested seen_slot_headers = let open Dal_slot_repr in diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index ae56f129cfe6..deb8d9ce56e2 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -452,9 +452,10 @@ module Dal : sig source:Signature.public_key_hash -> t tzresult - (** [candidates ctxt] returns the current list of slot for which - there is at least one candidate. *) - val candidates : t -> Dal_slot_repr.Header.t list + (** [candidates ctxt] returns the current list of slot for which there is at + least one candidate alongside the addresses that published them. *) + val candidates : + t -> (Dal_slot_repr.Header.t * Signature.public_key_hash) list (** [is_slot_index_attested ctxt slot_index] returns [true] if the [slot_index] is declared available by the protocol. [false] otherwise. If -- GitLab From beada6e50373beb2ff5a3501eed6da795d24b978 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Mon, 21 Oct 2024 12:05:03 +0200 Subject: [PATCH 3/6] DAL/Proto: extend the storage part of "slot_headers" to include commitments publishers This intermediate steps yields two TODOs: - Propagate the publisher info until dal_slot_repr where skip list cells are added - Implement a storage migration, as the encoding evolved --- src/proto_alpha/lib_plugin/RPC.ml | 2 +- src/proto_alpha/lib_protocol/alpha_context.mli | 4 +++- src/proto_alpha/lib_protocol/dal_slot_storage.ml | 7 ++++--- src/proto_alpha/lib_protocol/dal_slot_storage.mli | 12 +++++++----- src/proto_alpha/lib_protocol/storage.ml | 9 +++++++-- src/proto_alpha/lib_protocol/storage.mli | 5 ++++- 6 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 56a610eef18e..9f62c42cf03c 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -3117,7 +3117,7 @@ module Dal = struct let level = Option.value level ~default:(Level.current ctxt).level in let* result = Dal.Slot.find_slot_headers ctxt level in match result with - | Some l -> return l + | Some l -> return @@ List.map fst l | None -> Environment.Error_monad.tzfail @@ Published_slot_headers_not_initialized level diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 2b0a038666cc..a0194cc24a0d 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2875,7 +2875,9 @@ module Dal : sig context -> Header.t -> source:public_key_hash -> context tzresult val find_slot_headers : - context -> Raw_level.t -> Header.t list option tzresult Lwt.t + context -> + Raw_level.t -> + (Header.t * Signature.public_key_hash) list option tzresult Lwt.t val finalize_current_slot_headers : context -> context Lwt.t diff --git a/src/proto_alpha/lib_protocol/dal_slot_storage.ml b/src/proto_alpha/lib_protocol/dal_slot_storage.ml index b59e2166d6f2..c0e6f75f8342 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_storage.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_storage.ml @@ -31,9 +31,7 @@ let finalize_current_slot_headers ctxt = Storage.Dal.Slot.Headers.add ctxt (Raw_context.current_level ctxt).level - (* WIP: The correct handling of addresses associated to commitments will be - done in the next commits. *) - (Raw_context.Dal.candidates ctxt |> List.map fst) + (Raw_context.Dal.candidates ctxt) let compute_slot_headers_statuses ~is_slot_attested seen_slot_headers = let open Dal_slot_repr in @@ -104,6 +102,9 @@ let finalize_pending_slot_headers ctxt ~number_of_slots = match seen_slots with | None -> return (ctxt, Dal_attestation_repr.empty, []) | Some seen_slots -> + (* WIP: Handle tz addresses that published the commitments in the next + commits. *) + let seen_slots = List.map fst seen_slots in let slot_headers_statuses, attestation = let is_slot_attested slot = Raw_context.Dal.is_slot_index_attested diff --git a/src/proto_alpha/lib_protocol/dal_slot_storage.mli b/src/proto_alpha/lib_protocol/dal_slot_storage.mli index d93cb76463eb..746520a82800 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_storage.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_storage.mli @@ -44,14 +44,16 @@ - For every level below [current_level - attestation_lag], there should not be any slot in the storage. *) -(** [find_slot_headers ctxt level] returns [Some slot_headers] where [slot_headers] - are pending slots at level [level]. [None] is returned if no - [slot_header] was registered at this level. The function fails if - the reading into the context fails. *) +(** [find_slot_headers ctxt level] returns [Some slot_headers] where + [slot_headers] are pending slots at level [level] alongside the public key + hashes that published them. [None] is returned if no [slot_header] was + registered at this level. The function fails if the reading into the context + fails. *) val find_slot_headers : Raw_context.t -> Raw_level_repr.t -> - Dal_slot_repr.Header.t list option tzresult Lwt.t + (Dal_slot_repr.Header.t * Signature.public_key_hash) list option tzresult + Lwt.t (** [find_level_histories ctxt] returns the cells of the DAL skip list produced at the current level alongside their hashes. Returns [None] if no entry is diff --git a/src/proto_alpha/lib_protocol/storage.ml b/src/proto_alpha/lib_protocol/storage.ml index 8d295e9b4de1..6910691f62d5 100644 --- a/src/proto_alpha/lib_protocol/storage.ml +++ b/src/proto_alpha/lib_protocol/storage.ml @@ -2181,9 +2181,14 @@ module Dal = struct (* The size of the list below is at most equal to the [number_of_slots] as declared in the DAL parameters of the protocol. *) - type t = Dal_slot_repr.Header.t list + type t = (Dal_slot_repr.Header.t * Signature.public_key_hash) list - let encoding = Data_encoding.(list Dal_slot_repr.Header.encoding) + let encoding = + let open Data_encoding in + list + (obj2 + (req "slot_header" Dal_slot_repr.Header.encoding) + (req "publisher" Signature.Public_key_hash.encoding)) end) module History = diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 9250bbf2c8ed..2ae892ecf11d 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -1015,7 +1015,10 @@ module Dal : sig Non_iterable_indexed_data_storage with type t = Raw_context.t and type key = Raw_level_repr.t - and type value = Dal_slot_repr.Header.t list + and type value = + (* TODO: correctly handle the protocol migration part. This will be + done in the next commits. *) + (Dal_slot_repr.Header.t * Signature.public_key_hash) list (** This is a permanent storage for slot headers confirmed by the L1. *) module History : -- GitLab From be6c3489791a4aa428abb22f5a59303913dac3c5 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Wed, 23 Oct 2024 13:20:24 +0200 Subject: [PATCH 4/6] DAL/Proto: propagete slots publishers until dal_slot_repr when making SL cells In a follow-up MR, the publisher will be taken into account. It will be added to the cells of the skip list --- .../lib_protocol/alpha_context.mli | 10 ++++-- src/proto_alpha/lib_protocol/dal_slot_repr.ml | 9 +++-- .../lib_protocol/dal_slot_repr.mli | 10 ++++-- .../lib_protocol/dal_slot_storage.ml | 8 ++--- .../test/pbt/test_dal_slot_proof.ml | 34 +++++++++++++------ .../test/pbt/test_sc_rollup_encoding.ml | 22 ++++++++---- .../test/unit/test_dal_slot_proof.ml | 4 +-- .../test/test_octez_conversions.ml | 19 ++++++----- 8 files changed, 77 insertions(+), 39 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index a0194cc24a0d..d2370934ad69 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2930,7 +2930,10 @@ module Dal : sig t -> Raw_level.t -> number_of_slots:int -> - (Slot.Header.t * Attestation.attestation_status) list -> + (Slot.Header.t + * Signature.public_key_hash + * Attestation.attestation_status) + list -> t tzresult val update_skip_list : @@ -2938,7 +2941,10 @@ module Dal : sig History_cache.t -> Raw_level.t -> number_of_slots:int -> - (Slot.Header.t * Attestation.attestation_status) list -> + (Slot.Header.t + * Signature.public_key_hash + * Attestation.attestation_status) + list -> (t * History_cache.t) tzresult type proof diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.ml b/src/proto_alpha/lib_protocol/dal_slot_repr.ml index 1f168e3db3d1..602365a1656a 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.ml @@ -564,8 +564,11 @@ module History = struct let mk_unattested index = Content.Unattested Header.{published_level; index} in - (* TODO: Follow-up MR: Take the value of _s_status into account. *) - let attested_slot_headers = List.map fst slot_headers_with_statuses in + (* TODO: Follow-up MR: Take the value of _s_status and _s_publisher into + account. *) + let attested_slot_headers = + List.map (fun (slot, _pub, _status) -> slot) slot_headers_with_statuses + in (* Hypothesis: both lists are sorted in increasing order w.r.t. slots indices. *) let rec aux indices slots = @@ -594,7 +597,7 @@ module History = struct let open Result_syntax in let* () = List.iter_e - (fun (slot_header, _status) -> + (fun (slot_header, _slot_publisher, _status) -> error_unless Raw_level_repr.( published_level = slot_header.Header.id.published_level) diff --git a/src/proto_alpha/lib_protocol/dal_slot_repr.mli b/src/proto_alpha/lib_protocol/dal_slot_repr.mli index c73efb3b8c52..09c655731a35 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_slot_repr.mli @@ -278,7 +278,10 @@ module History : sig History_cache.t -> Raw_level_repr.t -> number_of_slots:int -> - (Header.t * Dal_attestation_repr.Accountability.attestation_status) list -> + (Header.t + * Signature.public_key_hash + * Dal_attestation_repr.Accountability.attestation_status) + list -> (t * History_cache.t) tzresult (** Similiar to {!update_skip_list}, but no cache is provided or @@ -287,7 +290,10 @@ module History : sig t -> Raw_level_repr.t -> number_of_slots:int -> - (Header.t * Dal_attestation_repr.Accountability.attestation_status) list -> + (Header.t + * Signature.public_key_hash + * Dal_attestation_repr.Accountability.attestation_status) + list -> t tzresult (** [equal a b] returns true iff a is equal to b. *) diff --git a/src/proto_alpha/lib_protocol/dal_slot_storage.ml b/src/proto_alpha/lib_protocol/dal_slot_storage.ml index c0e6f75f8342..2ad1a062bc87 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_storage.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_storage.ml @@ -35,10 +35,11 @@ let finalize_current_slot_headers ctxt = let compute_slot_headers_statuses ~is_slot_attested seen_slot_headers = let open Dal_slot_repr in - let fold_attested_slots (rev_attested_slot_headers, attestation) slot = + let fold_attested_slots (rev_attested_slot_headers, attestation) + (slot, slot_publisher) = let attestation_status = is_slot_attested slot in let rev_attested_slot_headers = - (slot, attestation_status) :: rev_attested_slot_headers + (slot, slot_publisher, attestation_status) :: rev_attested_slot_headers in let attestation = if @@ -102,9 +103,6 @@ let finalize_pending_slot_headers ctxt ~number_of_slots = match seen_slots with | None -> return (ctxt, Dal_attestation_repr.empty, []) | Some seen_slots -> - (* WIP: Handle tz addresses that published the commitments in the next - commits. *) - let seen_slots = List.map fst seen_slots in let slot_headers_statuses, attestation = let is_slot_attested slot = Raw_context.Dal.is_slot_index_attested 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 d3808cc558b1..b3f9781c035d 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 @@ -53,8 +53,9 @@ struct (* Introduce some intermediate types. *) - (** The slot is not confirmed (skipped) iff the boolean is [true]. *) - type slot_skipped = bool + (** The slot is not confirmed (skipped) iff the boolean is [true]. The flag is + attached to the hypothetical publisher of the slot. *) + type slot_skipped = bool * Signature.public_key_hash type level = int @@ -86,7 +87,7 @@ struct let curr_level = Raw_level_repr.of_int32_exn (Int32.of_int level) in let slots_headers = List.mapi - (fun sindex skip_slot -> + (fun sindex (skip_slot, slot_publisher) -> let index = Option.value_f (Dal_slot_index_repr.of_int_opt @@ -96,12 +97,13 @@ struct in ( Dal_slot_repr.Header. {id = {published_level = curr_level; index}; commitment}, + slot_publisher, skip_slot )) slots_data in let slots_headers = List.filter_map - (fun (slot, skip_slot) -> + (fun (slot, slot_publisher, skip_slot) -> let attestation_status = Dal_attestation_repr.Accountability. { @@ -110,7 +112,8 @@ struct is_proto_attested = not skip_slot; } in - if skip_slot then None else Some (slot, attestation_status)) + if skip_slot then None + else Some (slot, slot_publisher, attestation_status)) slots_headers in let*?@ cell, cache = @@ -123,8 +126,8 @@ struct in let slots_info = List.fold_left - (fun slots_info (slot, slot_status) -> - (polynomial, slot, slot_status) :: slots_info) + (fun slots_info (slot, slot_publisher, slot_status) -> + (polynomial, slot, slot_publisher, slot_status) :: slots_info) slots_info slots_headers in @@ -137,7 +140,7 @@ struct (** This function returns the (correct) information of a page to prove that it is confirmed, or None if the page's slot is skipped. *) - let request_confirmed_page (poly, slot, slot_status) = + let request_confirmed_page (poly, slot, _slot_publisher, slot_status) = let open Lwt_result_syntax in if not slot_status.Dal_attestation_repr.Accountability.is_proto_attested then @@ -152,7 +155,7 @@ struct (but the slot is not confirmed). Otherwise, we increment the publish_level field to simulate a non confirmed slot (as for even levels, no slot is confirmed. See {!populate_slots_history}). *) - let request_unconfirmed_page (poly, slot, slot_status) = + let request_unconfirmed_page (poly, slot, _slot_publisher, slot_status) = let open Lwt_result_syntax in let open Dal_slot_repr.Header in if not slot_status.Dal_attestation_repr.Accountability.is_proto_attested @@ -215,7 +218,12 @@ struct let tests = let gen_dal_config : levels QCheck2.Gen.t = - QCheck2.Gen.( + let open QCheck2 in + let gen_pkh = + let pkh, _, _ = Signature.generate_key ~algo:Ed25519 () in + Gen.return pkh + in + Gen.( let nb_slots = 0 -- Parameters.(dal_parameters.number_of_slots) in let nb_levels = 4 -- 30 in let* start_level = @@ -224,7 +232,11 @@ struct (* skip level 0 by adding 1 *) in (* The slot is confirmed iff the boolean is true *) - let slot = bool in + let slot = + let* slot_flag = bool in + let* slot_publisher = gen_pkh in + Gen.return (slot_flag, slot_publisher) + in let slots = list_size nb_slots slot in (* For each level, we generate the gap/delta w.r.t. the previous level, and the slots' flags (confirmed or not). *) 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 e24ca6075133..753a63085830 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 @@ -124,16 +124,19 @@ let pack_slots_headers_by_level list = let module SSH = Set.Make (struct type t = Dal_slot_repr.Header.t + * Signature.public_key_hash * Dal_attestation_repr.Accountability.attestation_status - let compare (a, _) (b, _) = + let compare (a, _, _) (b, _, _) = let open Dal_slot_repr.Header in Dal_slot_index_repr.compare a.id.index b.id.index end) in let map = List.fold_left (fun map - ((Dal_slot_repr.Header.{id = {published_level; _}; _}, _status) as sh) -> + (( Dal_slot_repr.Header.{id = {published_level; _}; _}, + _publisher, + _status ) as sh) -> let l = ML.find published_level map |> Option.value ~default:SSH.empty in @@ -157,6 +160,10 @@ let pack_slots_headers_by_level list = |> ML.bindings |> List.map (fun (k, ssh) -> (k, SSH.elements ssh)) +let gen_pkh = + let pkh, _, _ = Signature.generate_key ~algo:Ed25519 () in + Gen.return pkh + let gen_dal_slots_history () = let open Gen in let open Dal_slot_repr in @@ -164,11 +171,12 @@ let gen_dal_slots_history () = Tezos_protocol_alpha_parameters.Default_parameters.constants_test in let number_of_slots = constants.dal.number_of_slots in - (* Generate a list of (level * confirmed slot ID). *) - let* list = small_list (triple small_nat small_nat bool) in + (* Generate a list of (level * confirmed slot ID * public key hash * + attestation flag). *) + let* list = small_list (quad small_nat small_nat gen_pkh bool) in let list = List.rev_map - (fun (level, slot_index, is_proto_attested) -> + (fun (level, slot_index, publisher, is_proto_attested) -> let attestation_status = Dal_attestation_repr.Accountability. { @@ -188,6 +196,7 @@ let gen_dal_slots_history () = |> Option.value ~default:Index.zero in ( Header.{id = {published_level; index}; commitment = Commitment.zero}, + publisher, attestation_status )) list in @@ -197,7 +206,8 @@ let gen_dal_slots_history () = let slot_headers = (* Sort the list in the right ordering before adding slots to slots_history. *) List.sort_uniq - (fun ({Header.id = a; _}, _status) ({id = b; _}, _status) -> + (fun ({Header.id = a; _}, _publisher, _status) + ({id = b; _}, _publisher, _status) -> let c = Raw_level_repr.compare a.published_level b.published_level in diff --git a/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml b/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml index f767d21e5971..734802b9cd36 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_dal_slot_proof.ml @@ -70,7 +70,7 @@ struct Hist.update_skip_list_no_cache skip_list level - [(slot, mk_attested)] + [(slot, Signature.Public_key_hash.zero, mk_attested)] ~number_of_slots:Parameters.dal_parameters.number_of_slots in check_result result @@ -196,7 +196,7 @@ struct genesis_history genesis_history_cache level - [(slot, mk_attested)] + [(slot, Signature.Public_key_hash.zero, mk_attested)] in let* page_info, page_id = mk_page_info slot polynomial in produce_and_verify_proof diff --git a/src/proto_alpha/lib_sc_rollup_node/test/test_octez_conversions.ml b/src/proto_alpha/lib_sc_rollup_node/test/test_octez_conversions.ml index 614a3c5d26d2..2086d6c95195 100644 --- a/src/proto_alpha/lib_sc_rollup_node/test/test_octez_conversions.ml +++ b/src/proto_alpha/lib_sc_rollup_node/test/test_octez_conversions.ml @@ -229,30 +229,31 @@ let gen_slot_header_with_status = let attested_shards = if status then total_shards else 0 in Dal.Attestation.{total_shards; attested_shards; is_proto_attested = status} in + let* publisher = gen_pkh in let+ header = gen_slot_header in - (header, status) + (header, publisher, status) let gen_slot_headers_with_statuses = let open QCheck2.Gen in let size = int_bound 50 in let+ l = list_size size gen_slot_header_with_status in List.sort - (fun ((h1 : Octez_smart_rollup.Dal.Slot_header.t), _status1) - ((h2 : Octez_smart_rollup.Dal.Slot_header.t), _status2) -> + (fun ((h1 : Octez_smart_rollup.Dal.Slot_header.t), _publisher, _status1) + ((h2 : Octez_smart_rollup.Dal.Slot_header.t), _publisher, _status2) -> compare_slot_header_id h1.id h2.id) l |> fun l -> match l with | [] -> [] - | ((h : Octez_smart_rollup.Dal.Slot_header.t), _status) :: _ -> + | ((h : Octez_smart_rollup.Dal.Slot_header.t), _publisher, _status) :: _ -> let min_level = h.id.published_level in (* smallest level *) List.mapi - (fun i ((h : Octez_smart_rollup.Dal.Slot_header.t), status) -> + (fun i ((h : Octez_smart_rollup.Dal.Slot_header.t), publisher, status) -> (* patch the published level to comply with the invariants *) let published_level = Int32.(add min_level (of_int i)) in let h = {h with id = {h.id with published_level}} in - (published_level, [(h, status)])) + (published_level, [(h, publisher, status)])) l let gen_slot_history = @@ -264,8 +265,9 @@ let gen_slot_history = (fun (lvl, h) -> ( Raw_level.of_int32_exn lvl, List.map - (fun (h, status) -> + (fun (h, publisher, status) -> ( Sc_rollup_proto_types.Dal.Slot_header.of_octez ~number_of_slots h, + publisher, status )) h )) l @@ -294,8 +296,9 @@ let gen_slot_history_cache = (fun (lvl, h) -> ( Raw_level.of_int32_exn lvl, List.map - (fun (h, status) -> + (fun (h, publisher, status) -> ( Sc_rollup_proto_types.Dal.Slot_header.of_octez ~number_of_slots h, + publisher, status )) h )) l -- GitLab From cbac9b75da3ab05e05cb3d282a5bc316e5b723e1 Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Mon, 21 Oct 2024 11:35:17 +0200 Subject: [PATCH 5/6] DAL/Proto: handle the migration of published slot headers' map in storage The simplest way of migrating is to wipe the data published a few levels before the migration but not attested yet. --- src/proto_alpha/lib_protocol/init_storage.ml | 37 ++++++++++++++++++++ src/proto_alpha/lib_protocol/storage.mli | 2 -- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/proto_alpha/lib_protocol/init_storage.ml b/src/proto_alpha/lib_protocol/init_storage.ml index 9b04c21d56e7..af191f5656bb 100644 --- a/src/proto_alpha/lib_protocol/init_storage.ml +++ b/src/proto_alpha/lib_protocol/init_storage.ml @@ -109,6 +109,37 @@ let patch_script ctxt (address, hash, patched_code) = address ; return ctxt +(* This temporary function is meant to be used when migrating from Quebec to R. + It removes possible entries from the [Storage.Dal.Slot.Headers] map, as the + type of values in this map evolved. *) +let remove_old_published_dal_slot_headers ctxt ~level ~attestation_lag = + (* DAL/TODO: https://gitlab.com/tezos/tezos/-/issues/7562 + + Add a test that triggers this migration: + - Cover all corner cases + - Check that all data have been correctly wiped. + *) + let open Lwt_syntax in + (* This function removes all entries at levels [LVL] from + [Storage.Dal.Slot.Headers], where: + + max (0, level - attestation_lag) <= LVL <= level + *) + let rec aux ctxt n = + if Compare.Int.(n > attestation_lag) then + (* All entries have been wiped. *) + Lwt.return ctxt + else + match Raw_level_repr.sub level n with + | None -> + (* This happens when level < attestation_lag *) + Lwt.return ctxt + | Some pub_level -> + let* ctxt = Storage.Dal.Slot.Headers.remove ctxt pub_level in + aux ctxt (n + 1) + in + aux ctxt 0 + let prepare_first_block chain_id ctxt ~typecheck_smart_contract ~typecheck_smart_rollup ~level ~timestamp ~predecessor = let open Lwt_result_syntax in @@ -215,6 +246,12 @@ let prepare_first_block chain_id ctxt ~typecheck_smart_contract let* ctxt = Sc_rollup_refutation_storage.migrate_clean_refutation_games ctxt in + let*! ctxt = + remove_old_published_dal_slot_headers + ctxt + ~level + ~attestation_lag:parametric.dal.attestation_lag + in return (ctxt, []) (* End of alpha predecessor stitching. Comment used for automatic snapshot *) in diff --git a/src/proto_alpha/lib_protocol/storage.mli b/src/proto_alpha/lib_protocol/storage.mli index 2ae892ecf11d..26e919be8848 100644 --- a/src/proto_alpha/lib_protocol/storage.mli +++ b/src/proto_alpha/lib_protocol/storage.mli @@ -1016,8 +1016,6 @@ module Dal : sig with type t = Raw_context.t and type key = Raw_level_repr.t and type value = - (* TODO: correctly handle the protocol migration part. This will be - done in the next commits. *) (Dal_slot_repr.Header.t * Signature.public_key_hash) list (** This is a permanent storage for slot headers confirmed by the L1. *) -- GitLab From 52400503a677678c43d912729d063eab9ead282b Mon Sep 17 00:00:00 2001 From: "iguerNL@Functori" Date: Mon, 21 Oct 2024 11:40:27 +0200 Subject: [PATCH 6/6] DAL/Proto: add a TODO to rename an ill-named variable --- src/proto_alpha/lib_protocol/dal_slot_storage.ml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/proto_alpha/lib_protocol/dal_slot_storage.ml b/src/proto_alpha/lib_protocol/dal_slot_storage.ml index 2ad1a062bc87..ebacce2747c6 100644 --- a/src/proto_alpha/lib_protocol/dal_slot_storage.ml +++ b/src/proto_alpha/lib_protocol/dal_slot_storage.ml @@ -97,6 +97,11 @@ let finalize_pending_slot_headers ctxt ~number_of_slots = match Raw_level_repr.(sub raw_level dal.attestation_lag) with | None -> return (ctxt, Dal_attestation_repr.empty) | Some level_attested -> + (* TODO/DAL: https://gitlab.com/tezos/tezos/-/issues/7563 + + rename a level_attested into a published_level. The name level_attested + is misteading as it's equal to (current_)level - attestation_lag, which + rather corresponds to the publication level of slot headers. *) let* seen_slots = find_slot_headers ctxt level_attested in let*! ctxt = Storage.Dal.Slot.Headers.remove ctxt level_attested in let* ctxt, attestation, slot_headers_statuses = -- GitLab