diff --git a/src/lib_dal_node/attestable_slots.ml b/src/lib_dal_node/attestable_slots.ml index fc3cbdbf53171aa6cb20797ce87adf07cf3d7cd9..cf9ad3ddfe9d87a7be3caf76e7f50979bc5ef55b 100644 --- a/src/lib_dal_node/attestable_slots.ml +++ b/src/lib_dal_node/attestable_slots.ml @@ -60,7 +60,11 @@ let attested_just_after_migration ctxt ~attested_level = let* new_lag = get_attestation_lag ctxt ~level:attested_level in let* old_lag = let published_level = Int32.(sub attested_level new_lag) in - get_attestation_lag ctxt ~level:published_level + if published_level < 1l then + (* This makes the condition below false; which is correct assuming there's + no migration before level [new_lag + 1] (or so). *) + return new_lag + else get_attestation_lag ctxt ~level:published_level in return (old_lag > new_lag diff --git a/src/lib_dal_node/block_handler.ml b/src/lib_dal_node/block_handler.ml index 9a2f4e599376e1f6c8fe74ff8a48dbc4a33f2142..ca794598ef20257ef47e0547841400dd6762d470 100644 --- a/src/lib_dal_node/block_handler.ml +++ b/src/lib_dal_node/block_handler.ml @@ -217,7 +217,7 @@ let may_update_topics ctxt proto_parameters ~block_level = level, then skip-list cells were build using the previous protocol's encoding and parameters; while the plugin and parameters at [attested_level] are the ones for the new protocol (given that the migration already occurred). *) -let store_skip_list_cells ctxt cctxt dal_constants ~attested_level +let fetch_skip_list_cells ctxt cctxt dal_constants ~attested_level (module Plugin : Dal_plugin.T) = let open Lwt_result_syntax in let* cells_of_level = @@ -237,21 +237,37 @@ let store_skip_list_cells ctxt cctxt dal_constants ~attested_level ctxt ~level:(`Level pred_published_level))) in - let cells_of_level = - List.map - (fun (hash, cell, slot_index, cell_attestation_lag) -> - ( Dal_proto_types.Skip_list_hash.of_proto - Plugin.Skip_list.hash_encoding - hash, - Dal_proto_types.Skip_list_cell.of_proto - Plugin.Skip_list.cell_encoding - cell, - slot_index, - cell_attestation_lag )) - cells_of_level - in + List.map + (fun (hash, cell, slot_index, cell_attestation_lag) -> + ( Dal_proto_types.Skip_list_hash.of_proto + Plugin.Skip_list.hash_encoding + hash, + Dal_proto_types.Skip_list_cell.of_proto + Plugin.Skip_list.cell_encoding + cell, + slot_index, + cell_attestation_lag, + Plugin.Skip_list.proto_attestation_status cell + |> Option.map (fun s -> (s :> Types.header_status)) )) + cells_of_level + |> return + +let store_skip_list_cells ctxt ~attested_level skip_list_cells = let store = Node_context.get_store ctxt in - Store.Skip_list_cells.insert store ~attested_level cells_of_level + Store.Skip_list_cells.insert store ~attested_level skip_list_cells + +let fetch_and_store_skip_list_cells ctxt cctxt proto_params ~attested_level + (module Plugin : Dal_plugin.T) = + let open Lwt_result_syntax in + let* skip_list_cells = + fetch_skip_list_cells + ctxt + cctxt + proto_params + ~attested_level + (module Plugin : Dal_plugin.T) + in + store_skip_list_cells ctxt ~attested_level skip_list_cells (* This functions counts, for each slot, the number of shards attested by the bakers. *) let attested_shards_per_slot attestations slot_to_committee ~number_of_slots @@ -465,6 +481,20 @@ let process_commitments ctxt cctxt store proto_parameters block_level [@profiler.aggregate_s {verbosity = Notice} "publish_slot_data"])) slot_headers +let update_slot_headers_statuses store ~attested_level skip_list_cells = + List.iter + (fun (_hash, _cell, slot_index, cell_attestation_lag, status_opt) -> + let slot_level = + Int32.(sub attested_level (of_int cell_attestation_lag)) + in + let slot_id = Types.Slot_id.{slot_level; slot_index} in + Option.iter + (Slot_manager.update_slot_header_status store slot_id) + status_opt) + skip_list_cells + +(* The [Plugin] is that for the predecessor of the block level, it corresponds + to [prev_proto_parameters]. *) let process_finalized_block_data ctxt cctxt store ~prev_proto_parameters ~proto_parameters block_level (module Plugin : Dal_plugin.T) = let open Lwt_result_syntax in @@ -475,14 +505,21 @@ let process_finalized_block_data ctxt cctxt store ~prev_proto_parameters ~operations_metadata:`Never [@profiler.record_s {verbosity = Notice} "block_info"]) in + let* skip_list_cells = + (fetch_skip_list_cells + ctxt + cctxt + prev_proto_parameters + ~attested_level:block_level + (module Plugin : Dal_plugin.T) + [@profiler.record_s {verbosity = Notice} "fetch_skip_list_cells"]) + in let* () = if Node_context.supports_refutations ctxt then store_skip_list_cells ctxt - cctxt - prev_proto_parameters ~attested_level:block_level - (module Plugin : Dal_plugin.T) + skip_list_cells [@profiler.record_s {verbosity = Notice} "store_skip_list_cells"] else return_unit in @@ -491,14 +528,10 @@ let process_finalized_block_data ctxt cctxt store ~prev_proto_parameters block_info [@profiler.record_f {verbosity = Notice} "dal_attestation"]) in let () = - (Slot_manager.update_selected_slot_headers_statuses - ~block_level - ~attestation_lag:proto_parameters.Types.attestation_lag - ~number_of_slots:proto_parameters.number_of_slots - (Plugin.is_attested dal_attestation) - store - [@profiler.record_f - {verbosity = Notice} "update_selected_slot_headers_statuses"]) + update_slot_headers_statuses + store + ~attested_level:block_level + skip_list_cells in let*! () = (remove_unattested_slots_and_shards diff --git a/src/lib_dal_node/block_handler.mli b/src/lib_dal_node/block_handler.mli index b3140cb598be19259247b89b8410312359a16ce7..ce78e4fca8f29e8aa31b693352460398ea16f243 100644 --- a/src/lib_dal_node/block_handler.mli +++ b/src/lib_dal_node/block_handler.mli @@ -48,11 +48,11 @@ val new_finalized_head : launch_time:float -> (unit, tztrace) result Lwt.t -(** [store_skip_list_cells ctxt cctxt proto_parameters ~attested_level plugin] +(** [fetch_and_store_skip_list_cells ctxt cctxt proto_parameters ~attested_level plugin] extracts and stores the skip list cells from [block_info] at [block_level], using the encoding from the corresponding [plugin]. It is used to support DAL refutation. *) -val store_skip_list_cells : +val fetch_and_store_skip_list_cells : Node_context.t -> Rpc_context.t -> Tezos_dal_node_services.Types.proto_parameters -> diff --git a/src/lib_dal_node/dal_store_sqlite3.ml b/src/lib_dal_node/dal_store_sqlite3.ml index b15ff5f84708a9a32b82d4db3a3625bfb9fc9787..86141cbca8de72b7025f5ed68f30e891181f22a3 100644 --- a/src/lib_dal_node/dal_store_sqlite3.ml +++ b/src/lib_dal_node/dal_store_sqlite3.ml @@ -272,7 +272,7 @@ module Skip_list_cells = struct let open Lwt_result_syntax in with_connection store conn @@ fun conn -> List.iter_es - (fun (cell_hash, cell, slot_index, attestation_lag) -> + (fun (cell_hash, cell, slot_index, attestation_lag, _status_opt) -> let published_level = Int32.(sub attested_level (of_int attestation_lag)) in diff --git a/src/lib_dal_node/dal_store_sqlite3.mli b/src/lib_dal_node/dal_store_sqlite3.mli index c910e19156af8b83f1405a74db6581fb041b252e..2c8c489c05071e293017e156f304af35cd08230d 100644 --- a/src/lib_dal_node/dal_store_sqlite3.mli +++ b/src/lib_dal_node/dal_store_sqlite3.mli @@ -82,7 +82,8 @@ module Skip_list_cells : sig (Skip_list_hash.t * Skip_list_cell.t * Types.slot_index - * Types.attestation_lag) + * Types.attestation_lag + * Types.header_status option) list -> unit tzresult Lwt.t diff --git a/src/lib_dal_node/slot_manager.ml b/src/lib_dal_node/slot_manager.ml index 5f4029bbddc860bb7002796a7e79004af6219a34..936ac4ccca300ecd922a7fe09684f1a477897acf 100644 --- a/src/lib_dal_node/slot_manager.ml +++ b/src/lib_dal_node/slot_manager.ml @@ -793,15 +793,9 @@ module Statuses = struct | Error e -> fail (`Other e)) end -let update_selected_slot_headers_statuses ~block_level ~attestation_lag - ~number_of_slots attested_slots node_store = +let update_slot_header_status node_store slot_id status = let statuses_cache = Store.statuses_cache node_store in - Store.Statuses_cache.update_selected_slot_headers_statuses - ~block_level - ~attestation_lag - ~number_of_slots - attested_slots - statuses_cache + Store.Statuses_cache.update_slot_header_status statuses_cache slot_id status let get_slot_status ~slot_id ctxt = Statuses.find_status ctxt slot_id diff --git a/src/lib_dal_node/slot_manager.mli b/src/lib_dal_node/slot_manager.mli index a6f91df6f41ee5f5beeb710d33039ae2bede3417..66ef23994472417d983a70c43de399fab28626a9 100644 --- a/src/lib_dal_node/slot_manager.mli +++ b/src/lib_dal_node/slot_manager.mli @@ -180,23 +180,11 @@ val store_slot_headers : Store.t -> unit Lwt.t -(** [update_selected_slot_headers_statuses ~block_level ~attestation_lag - ~number_of_slots attested_slots store] updates the statuses of the - previously selected slots at level [block_level] - [attestation_lag] and - that were waiting for attestation. - - Slot headers whose indexes are in [attested_slots] are now set as - {!`Attested} in [store]. Those which are not are marked as - {!`Unattested} in the [store] if they previously had a "waiting for - attestation" status. -*) -val update_selected_slot_headers_statuses : - block_level:int32 -> - attestation_lag:int -> - number_of_slots:int -> - (Dal_plugin.slot_index -> bool) -> - Store.t -> - unit +(** [update_slot_header_status store slot_id status] updates the status of + [slot_id] setting it to [status], if the previous status was not present in + the store or was {!`Waiting_attestation}. *) +val update_slot_header_status : + Store.t -> Types.slot_id -> Types.header_status -> unit (** [get_slot_status ~slot_id store] returns the status associated to the accepted slot of id [slot_id] or [None] if no status is currently diff --git a/src/lib_dal_node/store.ml b/src/lib_dal_node/store.ml index 4003617a8d1f4ad90136bf2d7b5c77ce93bcb450..7c753af4b01387c2b16cdff8b8c0f95e49163e2a 100644 --- a/src/lib_dal_node/store.ml +++ b/src/lib_dal_node/store.ml @@ -671,34 +671,26 @@ module Statuses_cache = struct let get_slot_status = Slot_map.find_opt - let update_slot_headers_attestation ~published_level ~number_of_slots - ~attestation_lag t attested = - List.iter - (fun slot_index -> - let index = Types.Slot_id.{slot_level = published_level; slot_index} in - if attested slot_index then ( - Dal_metrics.slot_attested ~set:true slot_index ; - add_status t (`Attested attestation_lag) index) - else - let old_data_opt = get_slot_status t index in - Dal_metrics.slot_attested ~set:false slot_index ; - if Option.is_some old_data_opt then add_status t `Unattested index - else - (* There is no header that has been included in a block - and selected for this index. So, the slot cannot be - attested or unattested. *) - ()) - (0 -- (number_of_slots - 1)) - - let update_selected_slot_headers_statuses ~block_level ~attestation_lag - ~number_of_slots attested t = - let published_level = Int32.(sub block_level (of_int attestation_lag)) in - update_slot_headers_attestation - ~published_level - ~number_of_slots - ~attestation_lag - t - attested + let update_slot_header_status t slot_id status = + assert (status <> `Waiting_attestation) ; + (match get_slot_status t slot_id with + | None -> add_status t status slot_id + | Some `Unpublished -> assert (status = `Unpublished) + | Some `Waiting_attestation -> ( + match status with + | `Attested _lag -> add_status t status slot_id + | `Unattested -> add_status t status slot_id + | `Unpublished | `Waiting_attestation -> assert false) + | Some (`Attested _lag) -> + (* If a status was already inserted, then its value was either + [Unpublished] or [Waiting_attestation]. *) + assert false + | Some `Unattested -> assert false) ; + match status with + | `Attested _lag -> Dal_metrics.slot_attested ~set:true slot_id.slot_index + | `Unattested | `Unpublished | `Waiting_attestation -> + (* TODO: is the right way to update the metric here?? *) + Dal_metrics.slot_attested ~set:false slot_id.slot_index end module Commitment_indexed_cache = diff --git a/src/lib_dal_node/store.mli b/src/lib_dal_node/store.mli index 3ac6b9c9119a6ae0fe7eb68e9ea066a2cf392ec2..17e01942cb2332d1c0c7b0a8e35b1c1ecc825dbd 100644 --- a/src/lib_dal_node/store.mli +++ b/src/lib_dal_node/store.mli @@ -93,18 +93,10 @@ module Statuses_cache : sig type t - (** [update_selected_slot_headers_statuses ~block_level - ~attestation_lag ~number_of_slots attested is_attested store] - updates the status of all accepted slots at level [block_level - - attestation_lag] to either `Attested ([attested] returns [true]) - or `Unattested (when [attested] returns [false]). *) - val update_selected_slot_headers_statuses : - block_level:int32 -> - attestation_lag:int -> - number_of_slots:int -> - (int -> bool) -> - t -> - unit + (** [update_slot_header_status store slot_id status] updates the status of the + [slot_id] to [status]. *) + val update_slot_header_status : + t -> Types.slot_id -> Types.header_status -> unit (** [get_slot_status cache ~slot_id] returns the status associated to the given [slot_id], if any. *) @@ -278,7 +270,8 @@ module Skip_list_cells : sig (Skip_list_hash.t * Skip_list_cell.t * Types.slot_index - * Types.attestation_lag) + * Types.attestation_lag + * Types.header_status option) list -> unit tzresult Lwt.t diff --git a/src/lib_dal_node/store_cleanup.ml b/src/lib_dal_node/store_cleanup.ml index dccdd99d2f0b79ebd3a2f74e7ebef3efb8c0cf8e..1e839e2b3f5b485c049518530c63ca8dc2298dea 100644 --- a/src/lib_dal_node/store_cleanup.ml +++ b/src/lib_dal_node/store_cleanup.ml @@ -49,7 +49,7 @@ let clean_up_store_and_catch_up_for_refutation_support ctxt cctxt let*? dal_constants = Node_context.get_proto_parameters ctxt ~level:(`Level level) in - Block_handler.store_skip_list_cells + Block_handler.fetch_and_store_skip_list_cells ctxt cctxt dal_constants diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 6f2cfc167fd0b8eb486b9f600fe4475521b22e6e..0ee00d77bcd11dacd03942638f0fae824c7fac1d 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -507,7 +507,7 @@ let process_dal_rpc_result state delegate level round = function | `RPC_timeout -> let*! () = - Events.(emit failed_to_get_dal_attestations_in_time delegate) + Events.(emit failed_to_get_dal_attestations_in_time (delegate, level)) in return_none | `RPC_result (Error errs) -> @@ -567,7 +567,7 @@ let may_get_dal_content state consensus_vote = wait for a bit for the DAL node to provide an answer. *) Lwt.pick [ - (let*! () = Lwt_unix.sleep 0.5 in + (let*! () = Lwt_unix.sleep 0.75 in Lwt.return `RPC_timeout); (let*! tz_res = promise in Lwt.return (`RPC_result tz_res)); diff --git a/src/proto_alpha/lib_delegate/baking_events.ml b/src/proto_alpha/lib_delegate/baking_events.ml index 031f3d873fc57231989d4a426617fad176f50851..a151e8e42e5efeb6ca96fa9af1d61e0e849143b4 100644 --- a/src/proto_alpha/lib_delegate/baking_events.ml +++ b/src/proto_alpha/lib_delegate/baking_events.ml @@ -846,12 +846,14 @@ module Actions = struct ("trace", Error_monad.trace_encoding) let failed_to_get_dal_attestations_in_time = - declare_1 + declare_2 ~section ~name:"failed_to_get_attestations_in_time" ~level:Error - ~msg:"unable to get DAL attestation for {delegate} in time" + ~msg: + "unable to get DAL attestation for {delegate} in time for level {level}" ("delegate", Delegate_id.encoding) + ("level", Data_encoding.int32) let failed_to_inject_consensus_vote = declare_2 diff --git a/tezt/lib_tezos/dal_common.ml b/tezt/lib_tezos/dal_common.ml index 766468c2255ff29fe745ad3284884e70bcda102b..332aa7c7cc6a97fbfecab9804cb65bcd12fbd3e0 100644 --- a/tezt/lib_tezos/dal_common.ml +++ b/tezt/lib_tezos/dal_common.ml @@ -220,7 +220,7 @@ module Dal_RPC = struct | "waiting_attestation" -> Waiting_attestation | "attested" -> Attested legacy_attestation_lag | "unattested" -> Unattested - | "unpublished" -> Unattested + | "unpublished" -> Unpublished | exception _exn -> ( match JSON. diff --git a/tezt/tests/dal.ml b/tezt/tests/dal.ml index 70f0a38b5f7bfeefc965143ae009ea1d96eeabd4..6e986c54c042610273203213bcb7c3eef6d6eb94 100644 --- a/tezt/tests/dal.ml +++ b/tezt/tests/dal.ml @@ -5767,14 +5767,14 @@ let test_attestation_through_p2p ~batching_time_interval _protocol Log.info "Slot sucessfully attested" ; unit -module History_rpcs = struct +module Skip_list_rpcs = struct (* In the following function, no migration is performed (expect from genesis to alpha) when [migration_level] is equal to or smaller than 1. *) - let main_scenario ?(migration_level = 1) ~slot_index ~first_cell_level - ~first_dal_level ~last_confirmed_published_level protocol dal_parameters - client node dal_node = + let main_scenario ?(migration_level = 1) ~slot_index + ~last_confirmed_published_level protocol dal_parameters client node + dal_node = let module Map_int = Map.Make (Int) in - Log.info "slot_index = %d first_dal_level = %d" slot_index first_dal_level ; + Log.info "slot_index = %d" slot_index ; let client = Client.with_dal_node client ~dal_node in let slot_size = dal_parameters.Dal.Parameters.cryptobox.slot_size in let lag = dal_parameters.attestation_lag in @@ -5794,6 +5794,9 @@ module History_rpcs = struct let wait_mempool_injection = Node.wait_for node "operation_injected.v0" (fun _ -> Some ()) in + let wait_for_dal_node = + wait_for_layer1_final_block dal_node (level - 1) + in let* commitment = Helpers.publish_and_store_slot client @@ -5806,46 +5809,66 @@ module History_rpcs = struct let* () = wait_mempool_injection in let* () = bake_for client in let* _level = Node.wait_for_level node (level + 1) in + let* () = if level > 2 then wait_for_dal_node else unit in publish ~max_level (level + 1) (Map_int.add published_level commitment commitments) in - Log.info - "Publishing commitments in the previous protocol, from published level \ - %d to %d" - (starting_level + 1) - (migration_level + 1) ; + if migration_level > 1 then + Log.info + "Publishing commitments in the previous protocol, from published level \ + %d to %d" + (starting_level + 1) + migration_level ; let* commitments = - publish ~max_level:migration_level starting_level Map_int.empty + publish ~max_level:(migration_level - 1) starting_level Map_int.empty in - Log.info "Migrated to the next protocol." ; + if migration_level > 1 then Log.info "Migrated to the next protocol." ; - let last_attested_level = last_confirmed_published_level + lag in + let* new_proto_params = + Node.RPC.call node @@ RPC.get_chain_block_context_constants () + in + let new_lag = + JSON.( + new_proto_params |-> "dal_parametric" |-> "attestation_lag" |> as_int) + in + if new_lag <> lag then Log.info "new attestation_lag = %d" new_lag ; + let last_attested_level = last_confirmed_published_level + lag in + (* The maximum level that needs to be reached (we use +2 to make last + attested level final). *) + let max_level = last_attested_level + 2 in + Log.info + "last published_level = %d, last attested_level = %d, last level = %d" + last_confirmed_published_level + last_attested_level + max_level ; let wait_for_dal_node = wait_for_layer1_final_block dal_node last_attested_level in let* second_level_new_proto = Client.level client in - assert (second_level_new_proto = migration_level + 1) ; + assert (second_level_new_proto = migration_level) ; Log.info "Publish commitments in the new protocol, from published level %d to %d" (second_level_new_proto + 1) - (last_confirmed_published_level + 1) ; + last_confirmed_published_level ; let* commitments = publish - ~max_level:last_confirmed_published_level + ~max_level:(last_confirmed_published_level - 1) second_level_new_proto commitments in - let* () = - (* The maximum level that needs to be reached (we use +2 to make last + + (* The maximum level that needs to be reached (we use +2 to make last attested level final). *) - let max_level = last_attested_level + 2 in + let max_level = last_attested_level + 2 in + let* () = let* current_level = Node.get_level node in - let count = max_level + 1 - current_level in + let count = max_level - current_level in + Log.info "Current level is %d. Bake %d more blocks." current_level count ; bake_for ~count client in @@ -5858,35 +5881,12 @@ module History_rpcs = struct let at_least_one_attested_status = ref false in let rec check_cell cell ~check_level = - let* lag_at_check_level = - let block = Option.map string_of_int check_level in - let* dal_parameters = Dal.Parameters.from_client ?block client in - return dal_parameters.attestation_lag - in - let* lag_at_pred_check_level = - let block = - Option.fold - ~none:None - ~some:(fun level -> - if level <= 1 then None else Some (string_of_int (level - 1))) - check_level - in - let* dal_parameters = Dal.Parameters.from_client ?block client in - return dal_parameters.attestation_lag - in - (* Select the right lag while taking care of the false returned lag in the - migration block (pevious lag used for validation but parameters patched - at block finalization). *) - let lag = - if lag_at_check_level = lag_at_pred_check_level then lag_at_check_level - else lag_at_pred_check_level - in - let skip_list_kind = JSON.(cell |-> "kind" |> as_string) in let expected_skip_list_kind = "dal_skip_list" in Check.( (skip_list_kind = expected_skip_list_kind) string + ~__LOC__ ~error_msg:"Unexpected skip list kind: got %L, expected %R") ; let skip_list = JSON.(cell |-> "skip_list") in let cell_index = JSON.(skip_list |-> "index" |> as_int) in @@ -5898,14 +5898,16 @@ module History_rpcs = struct (match check_level with | Some level -> - assert (level >= first_dal_level) ; + assert (level >= 1) ; let expected_published_level = - if level = first_dal_level then (* the "level" of genesis *) 0 + if level = 1 then (* the "level" of genesis *) 0 + else if level > migration_level then level - new_lag else level - lag in Check.( (cell_level = expected_published_level) int + ~__LOC__ ~error_msg: "Unexpected cell's published level: got %L, expected %R") | None -> ()) ; @@ -5915,7 +5917,7 @@ module History_rpcs = struct | None -> () | Some level -> let expected_slot_index = - if level = first_dal_level then + if level = 1 then (* the "slot index" of genesis *) 0 else number_of_slots - 1 @@ -5923,23 +5925,28 @@ module History_rpcs = struct Check.( (cell_slot_index = expected_slot_index) int + ~__LOC__ ~error_msg:"Unexpected slot index: got %L, expected %R") in (if cell_index > 0 then let expected_cell_index = - ((cell_level - 1 - first_cell_level) * number_of_slots) - + cell_slot_index + ((cell_level - 1) * number_of_slots) + cell_slot_index in Check.( (cell_index = expected_cell_index) int + ~__LOC__ ~error_msg:"Unexpected cell index: got %L, expected %R")) ; let cell_kind = JSON.(content |-> "kind" |> as_string) in let published cell_level = (* - Cond 1: we publish at [slot_index] - Cond 2: the (published) [cell_level] is greater than - [starting_level] *) - cell_slot_index = slot_index && cell_level > starting_level + [starting_level] + - Cond 3: the (published) [cell_level] is smaller or equal to + [last_confirmed_published_level] *) + cell_slot_index = slot_index + && cell_level > starting_level + && cell_level <= last_confirmed_published_level in let expected_kind = if not (published cell_level) then "unpublished" @@ -5950,12 +5957,14 @@ module History_rpcs = struct Check.( (cell_kind = expected_kind) string + ~__LOC__ ~error_msg:"Unexpected cell kind: got %L, expected %R") ; (if cell_kind = "published" || cell_kind = "attested" then let commitment = JSON.(content |-> "commitment" |> as_string) in Check.( (commitment = Map_int.find cell_level commitments) string + ~__LOC__ ~error_msg:"Unexpected commitment: got %L, expected %R")) ; let back_pointers = JSON.(skip_list |-> "back_pointers" |> as_list) @@ -5995,11 +6004,12 @@ module History_rpcs = struct in let* () = wait_for_dal_node in Log.info "Check skip-list using commitments_history RPCs" ; - let* () = check_history first_dal_level in + let* () = check_history 1 in Check.( (!at_least_one_attested_status = true) bool + ~__LOC__ ~error_msg:"No cell with the 'attested' status has been visited") ; let rec call_cells_of_level level = @@ -6013,10 +6023,16 @@ module History_rpcs = struct in let cells = JSON.as_list cells in let num_cells = List.length cells in - let expected_num_cells = if level < lag then 0 else 32 in + let expected_num_cells = + if level < lag then 0 + else if level = migration_level + 1 then + (lag - new_lag + 1) * number_of_slots + else number_of_slots + in Check.( (num_cells = expected_num_cells) int + ~__LOC__ ~error_msg:"Unexpected number of cells: got %L, expected %R") ; let* () = Lwt_list.iter_s @@ -6048,22 +6064,50 @@ module History_rpcs = struct Check.( (commitment = expected_commitment) string + ~__LOC__ ~error_msg: (let msg = sf "Unexpected commitment at level %d: " level in - msg ^ ": got %L, expected %R")) ; + msg ^ "got %L, expected %R")) ; call_get_commitment (level + 1) in Log.info "Check fetching commitments from the skip-list store" ; let* () = call_get_commitment 2 in + let rec call_get_status level = + (* At [max_level] we'd get 404; at [max_level - 1] we get answer because + statuses are inserted at L1 head level + 1. *) + if level >= max_level then unit + else + let* status = + Dal_RPC.( + call dal_node @@ get_level_slot_status ~slot_level:level ~slot_index) + in + let expected_status = + if level <= migration_level - lag then Dal_RPC.Attested lag + else if level == migration_level + 1 - lag then Dal_RPC.Unattested + else if new_lag <> lag && level <= migration_level then + Dal_RPC.Unattested + else if level <= last_confirmed_published_level then + Dal_RPC.Attested lag + else Dal_RPC.Unpublished + in + Check.( + (status = expected_status) + Dal_common.Check.slot_id_status_typ + ~__LOC__ + ~error_msg: + (let msg = sf "Unexpected status at level %d: " level in + msg ^ "got %L, expected %R")) ; + call_get_status (level + 1) + in + Log.info "Check fetching statuses from the skip-list store" ; + let* () = call_get_status 2 in unit - let test_commitments_history_rpcs protocols = + let test_skip_list_rpcs protocols = let scenario protocol dal_parameters _ client node dal_node = main_scenario ~slot_index:3 - ~first_cell_level:0 - ~first_dal_level:1 ~last_confirmed_published_level:3 protocol dal_parameters @@ -6072,7 +6116,7 @@ module History_rpcs = struct dal_node in let tags = ["rpc"; "skip_list"] in - let description = "commitments history RPCs" in + let description = "skip-list RPCs" in scenario_with_layer1_and_dal_nodes ~tags ~operator_profiles:[3; 15] @@ -6080,7 +6124,7 @@ module History_rpcs = struct scenario protocols - let test_commitments_history_rpcs_with_migration ~migrate_from ~migrate_to + let test_skip_list_rpcs_with_migration ~migrate_from ~migrate_to ~migration_level = let slot_index = 3 in let scenario ~migrate_to ~migration_level dal_parameters = @@ -6097,15 +6141,13 @@ module History_rpcs = struct let last_confirmed_published_level = migration_level + 3 in main_scenario ~slot_index - ~first_cell_level:0 - ~first_dal_level:1 ~last_confirmed_published_level ~migration_level migrate_to dal_parameters in - let description = "test commitments history with migration" in + let description = "test skip-list RPCs with migration" in let tags = ["rpc"; "skip_list"] in test_l1_migration_scenario ~migrate_from @@ -12087,7 +12129,7 @@ let register ~protocols = scenario_with_layer1_and_dal_nodes ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) ~attestation_threshold:100 - ~attestation_lag:16 + ~attestation_lag:8 ~activation_timestamp:Now ~number_of_slots:8 ~operator_profiles:[0; 1; 2; 3; 4; 5; 6; 7] @@ -12200,7 +12242,7 @@ let register ~protocols = ~prover:false test_operator_profile protocols ; - History_rpcs.test_commitments_history_rpcs protocols ; + Skip_list_rpcs.test_skip_list_rpcs protocols ; scenario_with_layer1_and_dal_nodes ~tags:["amplification"] ~bootstrap_profile:true @@ -12510,7 +12552,7 @@ let tests_start_dal_node_around_migration ~migrate_from ~migrate_to = let register_migration ~migrate_from ~migrate_to = test_migration_plugin ~migration_level:11 ~migrate_from ~migrate_to ; - History_rpcs.test_commitments_history_rpcs_with_migration + Skip_list_rpcs.test_skip_list_rpcs_with_migration ~migration_level:11 ~migrate_from ~migrate_to ;