diff --git a/src/bin_dal_node/RPC_server.ml b/src/bin_dal_node/RPC_server.ml index 4d7815813d3d29e797a39cd40e92a1aa58fdfa3e..fca39cdeb20cf10504fe83dfae6072a432fa8148 100644 --- a/src/bin_dal_node/RPC_server.ml +++ b/src/bin_dal_node/RPC_server.ml @@ -170,7 +170,6 @@ module Slots_handlers = struct return (commitment, commitment_proof) | _ -> let cryptobox = Node_context.get_cryptobox ctxt in - let proto_parameters = Node_context.get_proto_parameters ctxt in let profile = Node_context.get_profile_ctxt ctxt in let* () = if not (Profile_manager.is_prover_profile profile) then @@ -188,6 +187,10 @@ module Slots_handlers = struct (Errors.other [Cannot_publish_on_slot_index slot_index]) | None | Some _ -> return_unit in + let* proto_parameters = + Node_context.get_proto_parameters ctxt + |> lwt_map_error (fun e -> `Other e) + in let slot_size = proto_parameters.cryptobox_parameters.slot_size in let slot_length = String.length slot in let*? slot_bytes = @@ -280,11 +283,15 @@ module Profile_handlers = struct Node_context.warn_if_attesters_not_delegates ctxt operator_profiles |> lwt_map_error (fun e -> `Other e) in - let proto_parameters = Node_context.get_proto_parameters ctxt in + let* proto_parameters = + Node_context.get_proto_parameters ctxt + |> lwt_map_error (fun e -> `Other e) + in + let number_of_slots = proto_parameters.Dal_plugin.number_of_slots in match Profile_manager.add_and_register_operator_profile (Node_context.get_profile_ctxt ctxt) - proto_parameters + ~number_of_slots gs_worker operator_profiles with @@ -439,51 +446,73 @@ module Profile_handlers = struct attested_level (of_int proto_parameters.Dal_plugin.attestation_lag)) in - let shards_store = Store.shards store in - let number_of_shards_stored slot_index = - let slot_id : Types.slot_id = - {slot_level = published_level; slot_index} + if published_level < 1l then + let slots = + Stdlib.List.init proto_parameters.number_of_slots (fun _ -> false) in - let+ number_stored_shards = - Store.Shards.number_of_shards_available - shards_store - slot_id - shard_indices + return (Types.Attestable_slots {slots; published_level}) + else + (* FIXME: https://gitlab.com/tezos/tezos/-/issues/7291 + + Normally, for checking whether the incentives are enabled we would + use the (parameters at) [attested_level]. However, the attestation + level may be in the future and we may not have the plugin for + it. *) + let* proto_parameters = + Node_context.get_proto_parameters ctxt ~level:published_level |> lwt_map_error (fun e -> `Other e) in - (slot_id, number_stored_shards) - in - let all_slot_indexes = - Utils.Infix.(0 -- (proto_parameters.number_of_slots - 1)) - in - let* number_of_stored_shards_per_slot = - List.map_es number_of_shards_stored all_slot_indexes - in - let* flags = - List.map_es - (fun (slot_id, num_stored) -> - let all_stored = num_stored = number_of_assigned_shards in - if (not all_stored) || not proto_parameters.incentives_enable then - return @@ all_stored - else - is_slot_attestable_with_traps - shards_store - proto_parameters.traps_fraction - pkh - shard_indices - slot_id) - number_of_stored_shards_per_slot - in - Lwt.dont_wait - (fun () -> - warn_missing_shards - store - pkh - published_level - number_of_assigned_shards - number_of_stored_shards_per_slot) - (fun _exn -> ()) ; - return (Types.Attestable_slots {slots = flags; published_level}) + + let shards_store = Store.shards store in + let number_of_shards_stored slot_index = + let slot_id : Types.slot_id = + {slot_level = published_level; slot_index} + in + let+ number_stored_shards = + Store.Shards.number_of_shards_available + shards_store + slot_id + shard_indices + |> lwt_map_error (fun e -> `Other e) + in + (slot_id, number_stored_shards) + in + let all_slot_indexes = + Utils.Infix.(0 -- (proto_parameters.number_of_slots - 1)) + in + let* number_of_stored_shards_per_slot = + List.map_es number_of_shards_stored all_slot_indexes + in + let* published_level_parameters = + Node_context.get_proto_parameters ctxt ~level:published_level + |> lwt_map_error (fun e -> `Other e) + in + let* flags = + List.map_es + (fun (slot_id, num_stored) -> + let all_stored = num_stored = number_of_assigned_shards in + if not published_level_parameters.incentives_enable then + return all_stored + else if not all_stored then return false + else + is_slot_attestable_with_traps + shards_store + published_level_parameters.traps_fraction + pkh + shard_indices + slot_id) + number_of_stored_shards_per_slot + in + Lwt.dont_wait + (fun () -> + warn_missing_shards + store + pkh + published_level + number_of_assigned_shards + number_of_stored_shards_per_slot) + (fun _exn -> ()) ; + return (Types.Attestable_slots {slots = flags; published_level}) in call_handler1 (fun () -> let open Lwt_result_syntax in @@ -500,8 +529,11 @@ module Profile_handlers = struct ~level:attestation_level |> Errors.other_lwt_result in + let* proto_parameters = + Node_context.get_proto_parameters ctxt + |> lwt_map_error (fun e -> `Other e) + in let store = Node_context.get_store ctxt in - let proto_parameters = Node_context.get_proto_parameters ctxt in get_attestable_slots ~shard_indices store diff --git a/src/bin_dal_node/accuser.ml b/src/bin_dal_node/accuser.ml index 5bb89bca60bc87cadcd4503a8e5c6384d4f00556..5bb5d49d9baf21a7103d996a6ac442d46aa1c48a 100644 --- a/src/bin_dal_node/accuser.ml +++ b/src/bin_dal_node/accuser.ml @@ -74,7 +74,9 @@ let inject_entrapment_evidences (type block_info) rpc_ctxt block = let open Lwt_result_syntax in let attested_level = (Plugin.block_shell_header block).level in - let proto_parameters = Node_context.get_proto_parameters node_ctxt in + let* proto_parameters = + Node_context.get_proto_parameters node_ctxt ~level:attested_level + in when_ proto_parameters.incentives_enable (fun () -> let published_level = (* FIXME: https://gitlab.com/tezos/tezos/-/issues/4612 diff --git a/src/bin_dal_node/amplificator.ml b/src/bin_dal_node/amplificator.ml index de870bb215c2f2f0e6d922837d75809cf598f5ed..13697381c3b135ca60ac1ff4ae238b22229b5141 100644 --- a/src/bin_dal_node/amplificator.ml +++ b/src/bin_dal_node/amplificator.ml @@ -475,7 +475,7 @@ let try_amplification commitment slot_metrics slot_id amplificator = let open Lwt_result_syntax in let node_ctxt = amplificator.node_ctxt in let node_store = Node_context.get_store node_ctxt in - let proto_parameters = Node_context.get_proto_parameters node_ctxt in + let* proto_parameters = Node_context.get_proto_parameters node_ctxt in let number_of_shards = proto_parameters.cryptobox_parameters.number_of_shards in diff --git a/src/bin_dal_node/daemon.ml b/src/bin_dal_node/daemon.ml index dd27d32ef22b575de5d81d0ed5feafcde710fda5..4e632a767ee09e78955769628265f806ce9a22f2 100644 --- a/src/bin_dal_node/daemon.ml +++ b/src/bin_dal_node/daemon.ml @@ -248,10 +248,22 @@ module Handler = struct cryptobox message_id) in - if res = `Valid then - Option.iter - (Slot_manager.maybe_register_trap ctxt message_id) - message ; + (if res = `Valid then + let store = Node_context.get_store ctxt in + let traps_store = Store.traps store in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/7742 + The [proto_parameters] are those for the last known finalized + level, which may differ from those of the slot level. This + will be an issue when the value of the [traps_fraction] + changes. (We cannot use {!Node_context.get_proto_parameters}, + as it is not monad-free; we'll need to use mapping from levels + to parameters.) *) + Option.iter + (Slot_manager.maybe_register_trap + traps_store + ~traps_fraction:proto_parameters.traps_fraction + message_id) + message) ; res | other -> (* 4. In the case the message id is not Valid. *) @@ -395,15 +407,10 @@ module Handler = struct in Profile_manager.on_new_head (Node_context.get_profile_ctxt ctxt) - proto_parameters + ~number_of_slots:proto_parameters.number_of_slots (Node_context.get_gs_worker ctxt) committee - let get_constants ctxt cctxt ~level = - let open Lwt_result_syntax in - let*? (module Plugin) = Node_context.get_plugin_for_level ctxt ~level in - Plugin.get_constants `Main (`Level level) cctxt - let store_skip_list_cells (type block_info) ctxt cctxt dal_constants (block_info : block_info) block_level (module Plugin : Dal_plugin.T with type block_info = block_info) = @@ -419,7 +426,8 @@ module Handler = struct cctxt ~dal_constants ~pred_publication_level_dal_constants: - (lazy (get_constants ctxt cctxt ~level:pred_published_level)) + (lazy + (Node_context.get_proto_parameters ctxt ~level:pred_published_level)) in let cells_of_level = List.map @@ -544,7 +552,9 @@ module Handler = struct Node_context.get_plugin_for_level ctxt ~level:pred_level in let* block_info = Plugin.block_info cctxt ~block ~metadata:`Always in - let* dal_constants = get_constants ctxt cctxt ~level:block_level in + let* dal_constants = + Node_context.get_proto_parameters ctxt ~level:block_level + in let* () = if dal_constants.Dal_plugin.feature_enable then let* slot_headers = Plugin.get_published_slot_headers block_info in @@ -665,7 +675,6 @@ module Handler = struct let open Lwt_result_syntax in let stream = Crawler.finalized_heads_stream crawler in let rec loop () = - let proto_parameters = Node_context.get_proto_parameters ctxt in let cryptobox = Node_context.get_cryptobox ctxt in let*! next_final_head = Lwt_stream.get stream in match next_final_head with @@ -673,6 +682,18 @@ module Handler = struct | Some (_finalized_hash, finalized_shell_header) -> let level = finalized_shell_header.level in let () = Node_context.set_last_finalized_level ctxt level in + let* () = + (* FIXME: https://gitlab.com/tezos/tezos/-/issues/7291 + We should use the head level instead. *) + Node_context.may_add_plugin + ctxt + cctxt + ~proto_level:finalized_shell_header.proto_level + ~block_level:level + in + let* proto_parameters = + Node_context.get_proto_parameters ctxt ~level + in (* At each potential published_level [level], we prefetch the committee for its corresponding attestation_level (that is: level + attestation_lag - 1). This is in particular used by GS @@ -692,15 +713,6 @@ module Handler = struct in return_unit in - let* () = - (* FIXME: https://gitlab.com/tezos/tezos/-/issues/7291 - We should use the head level instead. *) - Node_context.may_add_plugin - ctxt - cctxt - ~proto_level:finalized_shell_header.proto_level - ~block_level:level - in Gossipsub.Worker.Validate_message_hook.set (gossipsub_app_messages_validation ctxt @@ -799,12 +811,11 @@ let update_timing_shard_received node_ctxt shards_timing_table slot_id in timing -let connect_gossipsub_with_p2p gs_worker transport_layer node_store node_ctxt - amplificator = +let connect_gossipsub_with_p2p proto_parameters gs_worker transport_layer + node_store node_ctxt amplificator = let open Gossipsub in - let proto_parameters = Node_context.get_proto_parameters node_ctxt in let timing_table_size = - 2 * proto_parameters.attestation_lag + 2 * proto_parameters.Dal_plugin.attestation_lag * proto_parameters.cryptobox_parameters.number_of_shards * proto_parameters.number_of_slots in @@ -1065,27 +1076,28 @@ let update_and_register_profiles ctxt = let open Lwt_result_syntax in let profile_ctxt = Node_context.get_profile_ctxt ctxt in let gs_worker = Node_context.get_gs_worker ctxt in - let proto_parameters = Node_context.get_proto_parameters ctxt in + let* proto_parameters = Node_context.get_proto_parameters ctxt in let profile_ctxt = - Profile_manager.register_profile profile_ctxt proto_parameters gs_worker + Profile_manager.register_profile + profile_ctxt + ~number_of_slots:proto_parameters.number_of_slots + gs_worker in let*! () = Node_context.set_profile_ctxt ctxt profile_ctxt in return_unit -(* This function fetches the protocol plugins for levels for which it is needed - to add skip list cells. It starts by computing the oldest level at which it - will be needed to add skip list cells. *) +(* This function fetches the protocol plugins for levels in the past for which + the node may need a plugin, namely for adding skip list cells, or for + obtaining the protocol parameters. + + Concerning the skip list, getting the plugin is (almost) necessary as skip + list cells are stored in the storage for a certain period and + [store_skip_list_cells] needs the L1 context for levels in this period. (It + would actually not be necessary to go as far in the past, because the + protocol parameters and the relevant encodings do not change for now, so the + head plugin could be used). *) let get_proto_plugins cctxt profile_ctxt ~last_processed_level ~first_seen_level head_level proto_parameters = - (* We resolve the plugins for all levels starting with [(max - last_processed_level (head_level - storage_period)], or (max - last_processed_level (head_level - storage_period) - (attestation_lag - - 1))] in case the node supports refutations. This is necessary as skip list - cells are stored for attested levels is this storage period and - [store_skip_list_cells] needs the L1 context for these levels. (It would - actually not be necessary to go as far in the past, because the protocol - parameters and the relevant encodings do not change for now, so the head - plugin could be used). *) let storage_period = get_storage_period profile_ctxt proto_parameters head_level first_seen_level in @@ -1097,7 +1109,10 @@ let get_proto_plugins cctxt profile_ctxt ~last_processed_level ~first_seen_level let first_level = if Profile_manager.supports_refutations profile_ctxt then Int32.sub first_level (Int32.of_int (skip_list_offset proto_parameters)) - else first_level + else + (* The DAL node may need the protocol parameters [attestation_lag] in the + past wrt to the head level. *) + Int32.sub first_level (Int32.of_int proto_parameters.attestation_lag) in let first_level = Int32.(max 1l first_level) in Proto_plugins.initial_plugins cctxt ~first_level ~last_level:head_level @@ -1125,7 +1140,7 @@ let clean_up_store ctxt cctxt ~last_processed_level ~first_seen_level head_level let* block_info = Plugin.block_info cctxt ~block:(`Level level) ~metadata:`Always in - let* dal_constants = Handler.get_constants ctxt cctxt ~level in + let* dal_constants = Node_context.get_proto_parameters ctxt ~level in Handler.store_skip_list_cells ctxt cctxt @@ -1355,7 +1370,7 @@ let run ~data_dir ~configuration_override = let+ profile_ctxt = build_profile_context config in Profile_manager.resolve_random_observer_profile profile_ctxt - proto_parameters + ~number_of_slots:proto_parameters.number_of_slots in let*? () = Profile_manager.validate_slot_indexes @@ -1494,6 +1509,7 @@ let run ~data_dir ~configuration_override = (* Activate the p2p instance. *) let shards_store = Store.shards store in connect_gossipsub_with_p2p + proto_parameters gs_worker transport_layer shards_store diff --git a/src/bin_dal_node/node_context.ml b/src/bin_dal_node/node_context.ml index 308268113b97ff68b9c12206f91a9e676b6c2ce2..c565e3ea89e3712a38973f1bd0f5727dbb6a1a92 100644 --- a/src/bin_dal_node/node_context.ml +++ b/src/bin_dal_node/node_context.ml @@ -76,6 +76,8 @@ let init config profile_ctxt cryptobox shards_proofs_precomputation last_finalized_level; } +let get_tezos_node_cctxt ctxt = ctxt.tezos_node_cctxt + let may_reconstruct ~reconstruct slot_id t = let open Lwt_result_syntax in let p = @@ -113,6 +115,16 @@ let get_all_plugins ctxt = Proto_plugins.to_list ctxt.proto_plugins let set_proto_plugins ctxt proto_plugins = ctxt.proto_plugins <- proto_plugins +let get_proto_parameters ?level ctxt = + let open Lwt_result_syntax in + match level with + | None -> return ctxt.proto_parameters + | Some level -> + (* get the plugin from the plugin cache *) + let*? (module Plugin) = get_plugin_for_level ctxt ~level in + let cctxt = get_tezos_node_cctxt ctxt in + Plugin.get_constants `Main (`Level level) cctxt + let storage_period ctxt proto_parameters = match ctxt.config.history_mode with | Full -> `Always @@ -159,8 +171,6 @@ let get_config ctxt = ctxt.config let get_cryptobox ctxt = ctxt.cryptobox -let get_proto_parameters ctxt = ctxt.proto_parameters - let set_last_finalized_level ctxt level = ctxt.last_finalized_level <- level let get_last_finalized_level ctxt = ctxt.last_finalized_level @@ -171,8 +181,6 @@ let get_store ctxt = ctxt.store let get_gs_worker ctxt = ctxt.gs_worker -let get_tezos_node_cctxt ctxt = ctxt.tezos_node_cctxt - let get_neighbors_cctxts ctxt = ctxt.neighbors_cctxts let get_ongoing_amplifications ctxt = ctxt.ongoing_amplifications diff --git a/src/bin_dal_node/node_context.mli b/src/bin_dal_node/node_context.mli index 5116a7feed9af0a8d7a480119e21f82313d4453f..088bb3d3a43c1845706696722c1ea83b4dd5fb44 100644 --- a/src/bin_dal_node/node_context.mli +++ b/src/bin_dal_node/node_context.mli @@ -99,8 +99,12 @@ val get_config : t -> Configuration_file.t (** [get_cryptobox ctxt] returns the DAL node's cryptobox *) val get_cryptobox : t -> Cryptobox.t -(** [get_proto_parameters ctxt] returns the DAL node's current protocol parameters. *) -val get_proto_parameters : t -> Dal_plugin.proto_parameters +(** [get_proto_parameters ?level ctxt] returns the DAL node's protocol + parameters stored in the context, when [level] is not provided. If [level] + is provided, then the protocol parameters for that level are fetched via the + relevant plugin. *) +val get_proto_parameters : + ?level:int32 -> t -> Dal_plugin.proto_parameters tzresult Lwt.t (** Update the node's last finalized level. *) val set_last_finalized_level : t -> int32 -> unit diff --git a/src/bin_dal_node/profile_manager.ml b/src/bin_dal_node/profile_manager.ml index 5476dd892af941aa4a820bacd1cf7ef986efa861..801f73cb4e2393ea37fc578e517d98d6ac0cbd06 100644 --- a/src/bin_dal_node/profile_manager.ml +++ b/src/bin_dal_node/profile_manager.ml @@ -73,7 +73,7 @@ let merge_profiles ~lower_prio ~higher_prio = | Random_observer, ((Operator _ | Bootstrap) as profile) -> profile | (Operator _ | Bootstrap), Random_observer -> Random_observer -let add_and_register_operator_profile t proto_parameters gs_worker +let add_and_register_operator_profile t ~number_of_slots gs_worker (operator_profile : Operator_profile.t) = match t with | Types.Bootstrap -> None @@ -82,7 +82,7 @@ let add_and_register_operator_profile t proto_parameters gs_worker List.iter (fun slot_index -> Join {slot_index; pkh} |> Gossipsub.Worker.(app_input gs_worker)) - Utils.Infix.(0 -- (proto_parameters.Dal_plugin.number_of_slots - 1)) + Utils.Infix.(0 -- (number_of_slots - 1)) in Some Types.( @@ -96,15 +96,15 @@ let add_and_register_operator_profile t proto_parameters gs_worker "Profile_manager.add_and_register_operator_profile: random observer \ should have a slot index assigned at this point" -let resolve_random_observer_profile t proto_parameters = +let resolve_random_observer_profile t ~number_of_slots = match t with | Types.Bootstrap | Operator _ -> t | Random_observer -> - let slot_index = Random.int proto_parameters.Dal_plugin.number_of_slots in + let slot_index = Random.int number_of_slots in let operator_profile = Operator_profile.make ~observers:[slot_index] () in Operator operator_profile -let register_profile t proto_parameters gs_worker = +let register_profile t ~number_of_slots gs_worker = match t with | Types.Bootstrap -> t | Random_observer -> @@ -115,7 +115,7 @@ let register_profile t proto_parameters gs_worker = let t_opt = add_and_register_operator_profile empty - proto_parameters + ~number_of_slots gs_worker operator_profile in @@ -157,9 +157,9 @@ let join_topics_for_operator gs_worker committee slots = (* FIXME: https://gitlab.com/tezos/tezos/-/issues/5934 We need a mechanism to ease the tracking of newly added/removed topics. Especially important for bootstrap nodes as the cross product can grow quite large. *) -let join_topics_for_bootstrap proto_parameters gs_worker committee = +let join_topics_for_bootstrap ~number_of_slots gs_worker committee = (* Join topics for all combinations of (all slots) * (all pkh in comittee) *) - for slot_index = 0 to proto_parameters.Dal_plugin.number_of_slots - 1 do + for slot_index = 0 to number_of_slots - 1 do Signature.Public_key_hash.Map.iter (fun pkh _shards -> let topic = Types.Topic.{slot_index; pkh} in @@ -168,13 +168,13 @@ let join_topics_for_bootstrap proto_parameters gs_worker committee = committee done -let on_new_head t proto_parameters gs_worker committee = +let on_new_head t ~number_of_slots gs_worker committee = match t with | Types.Random_observer -> Stdlib.failwith "Profile_manager.add_operator_profiles: random observer should have a \ slot index assigned at this point" - | Bootstrap -> join_topics_for_bootstrap proto_parameters gs_worker committee + | Bootstrap -> join_topics_for_bootstrap ~number_of_slots gs_worker committee | Operator op -> (* The topics associated to observers and producers can change if there new active bakers. However, for attesters, new slots diff --git a/src/bin_dal_node/profile_manager.mli b/src/bin_dal_node/profile_manager.mli index a4e1a5ce0b15ac0f1d823c18e9c6e9d9f13d73dd..631896ad580fb380536a576af1fc290527fde428 100644 --- a/src/bin_dal_node/profile_manager.mli +++ b/src/bin_dal_node/profile_manager.mli @@ -69,7 +69,7 @@ val operator : Operator_profile.t -> t priority. *) val merge_profiles : lower_prio:t -> higher_prio:t -> t -(** [add_and_register_operator_profile t proto_parameters gs_worker +(** [add_and_register_operator_profile t ~number_of_slots gs_worker operator_profile] adds the new [operator_profile] to [t]. It registers any new attester profile within [operator_profile] with gossipsub, that is, it instructs the [gs_worker] to join the corresponding topics. @@ -80,12 +80,12 @@ val merge_profiles : lower_prio:t -> higher_prio:t -> t It assumes the current profile is not a random observer. *) val add_and_register_operator_profile : t -> - Dal_plugin.proto_parameters -> + number_of_slots:int -> Gossipsub.Worker.t -> Operator_profile.t -> t option -(** [register_profile t proto_parameters gs_worker] does the following: +(** [register_profile t ~number_of_slots gs_worker] does the following: - It registers the attester profiles within [t] with gossipsub, that is, it instructs the [gs_worker] to join the corresponding topics. @@ -95,8 +95,7 @@ val add_and_register_operator_profile : slot index. The function returns the updated profile. *) -val register_profile : - t -> Dal_plugin.proto_parameters -> Gossipsub.Worker.t -> t +val register_profile : t -> number_of_slots:int -> Gossipsub.Worker.t -> t (** Checks that each producer profile only refers to slot indexes strictly smaller than [number_of_slots]. This may not be the case when the profile @@ -104,11 +103,11 @@ val register_profile : slots. Returns an [Invalid_slot_index] error if the check fails. *) val validate_slot_indexes : t -> number_of_slots:int -> unit tzresult -(** [on_new_head t proto_parameters gs_worker committee] performs profile-related +(** [on_new_head t ~number_of_slots gs_worker committee] performs profile-related actions that depend on the current head, more precisely on the current committee. *) val on_new_head : t -> - Dal_plugin.proto_parameters -> + number_of_slots:int -> Gossipsub.Worker.t -> Committee_cache.committee -> unit @@ -129,9 +128,8 @@ val get_attested_data_default_store_period : This function is called when generating an observer profile from a random profile before launching a DAL node, as implemented in the - daemon. -*) -val resolve_random_observer_profile : t -> Dal_plugin.proto_parameters -> t + daemon. *) +val resolve_random_observer_profile : t -> number_of_slots:int -> t (** Returns [true] iff the node should support refutation games. *) val supports_refutations : t -> bool diff --git a/src/bin_dal_node/slot_manager.ml b/src/bin_dal_node/slot_manager.ml index 228c5065e40de8fb95b68bcb4d86a9be92ad9862..c4d4b9a190e813317725f41e115cf3ba937cf072 100644 --- a/src/bin_dal_node/slot_manager.ml +++ b/src/bin_dal_node/slot_manager.ml @@ -199,21 +199,13 @@ let commit cryptobox polynomial = (* Main functions *) -let maybe_register_trap ctxt message_id message = - let proto_parameters = Node_context.get_proto_parameters ctxt in +let maybe_register_trap traps_store ~traps_fraction message_id message = let delegate = message_id.Types.Message_id.pkh in let Types.Message.{share; shard_proof} = message in let Types.Message_id.{slot_index; level; shard_index; _} = message_id in - let trap_res = - Trap.share_is_trap - ~traps_fraction:proto_parameters.traps_fraction - delegate - share - in + let trap_res = Trap.share_is_trap ~traps_fraction delegate share in match trap_res with | Ok true -> - let store = Node_context.get_store ctxt in - let traps_store = Store.traps store in let slot_id = Types.Slot_id.{slot_index; slot_level = level} in Store.Traps.add traps_store @@ -317,7 +309,16 @@ let publish_proved_shards ctxt (slot_id : Types.slot_id) ~level_committee pkh; } in - maybe_register_trap ctxt message_id message ; + let store = Node_context.get_store ctxt in + let traps_store = Store.traps store in + let traps_fraction = proto_parameters.traps_fraction in + let () = + maybe_register_trap + traps_store + ~traps_fraction + message_id + message + in Gossipsub.Worker.( Publish_message {message; topic; message_id} |> app_input gs_worker) ; @@ -390,7 +391,10 @@ let get_slot_shard (store : Store.t) (slot_id : Types.slot_id) shard_index = let get_slot_pages ~reconstruct_if_missing node_context slot_id = let open Lwt_result_syntax in - let proto_parameters = Node_context.get_proto_parameters node_context in + let* proto_parameters = + Node_context.get_proto_parameters node_context + |> lwt_map_error (fun e -> `Other e) + in let page_size = proto_parameters.cryptobox_parameters.page_size in let* slot = get_slot_content ~reconstruct_if_missing node_context slot_id in (* The slot size `Bytes.length slot` should be an exact multiple of `page_size`. diff --git a/src/bin_dal_node/slot_manager.mli b/src/bin_dal_node/slot_manager.mli index 683d56e42b409b0c510a3963db920cb250fb9370..4d415fffe886f1e7f1a2e4a844557a1445767f5c 100644 --- a/src/bin_dal_node/slot_manager.mli +++ b/src/bin_dal_node/slot_manager.mli @@ -199,10 +199,13 @@ val get_slot_shard : Types.shard_index -> (Cryptobox.shard, [Errors.other | Errors.not_found]) result Lwt.t -(** [maybe_register_trap ctxt message_id message] checks if the given - message is a trap according to [Trap.share_is_trap]. If the share - is identified as a trap, it is stored in the traps cache of the - DAL node store. Otherwise does nothing. -*) +(** [maybe_register_trap traps_store ~traps_fraction message_id message] checks + if the given message is a trap according to [Trap.share_is_trap]. If the + share is identified as a trap, it is stored in the traps cache of the DAL + node store. Otherwise does nothing. *) val maybe_register_trap : - Node_context.t -> Types.Message_id.t -> Types.Message.t -> unit + Store.Traps.t -> + traps_fraction:Q.t -> + Types.Message_id.t -> + Types.Message.t -> + unit diff --git a/tezt/tests/dal.ml b/tezt/tests/dal.ml index 3f0a368a7d2c3981bb38e08a44e69c395468feee..e82e8a4a1b3b229ba9c396a8fb0a251ed6cecc9e 100644 --- a/tezt/tests/dal.ml +++ b/tezt/tests/dal.ml @@ -3959,7 +3959,7 @@ let test_dal_node_join_topic _protocol parameters _cryptobox _node _client *) let generic_gs_messages_exchange protocol parameters _cryptobox node client dal_node1 ~mk_dal_node2 ~expect_app_notification ~is_first_slot_attestable = - let* dal_node2 = mk_dal_node2 protocol parameters in + let* node2, dal_node2 = mk_dal_node2 protocol parameters in let* () = Dal_common.Helpers.connect_nodes_via_p2p @@ -4041,6 +4041,16 @@ let generic_gs_messages_exchange protocol parameters _cryptobox node client and* () = waiter_receive_shards and* () = waiter_app_notifs in + let* () = + match node2 with + | None -> unit + | Some node2 -> + (* We need that this node reaches level 2; otherwise, the RPC call to + [get_attestable_slots] may fail. *) + let* _level = Node.wait_for_level node2 2 in + unit + in + (* Check that dal_node2 has the shards needed by attester account1/pkh1 to attest the slot with index 0. *) let* res = @@ -4070,13 +4080,14 @@ let test_dal_node_gs_valid_messages_exchange _protocol parameters _cryptobox client dal_node1 ~mk_dal_node2:(fun _protocol _parameters -> - Dal_node.create ~node () |> return) + let dal_node2 = Dal_node.create ~node () in + (None, dal_node2) |> return) ~expect_app_notification:true ~is_first_slot_attestable:true (* Create a DAL node whose DAL parameters are not compatible with those in [parameters]. For that, the redundancy_factor field is multiplied by 2. *) -let make_invalid_dal_node protocol parameters = +let make_invalid_dal_node node1 protocol parameters = (* Create another L1 node with different DAL parameters. *) let* node2, _client2, _xdal_parameters2 = let crypto_params = parameters.Dal.Parameters.cryptobox in @@ -4087,10 +4098,13 @@ let make_invalid_dal_node protocol parameters = in setup_node ~protocol ~parameter_overrides () in + Node.add_peer node2 node1 ; + let* () = Node.terminate node2 in + let* () = Node.run node2 [] in (* Create a second DAL node with node2 and client2 as argument (so different DAL parameters compared to dal_node1. *) let dal_node2 = Dal_node.create ~node:node2 () in - return dal_node2 + return (Some node2, dal_node2) let test_dal_node_gs_invalid_messages_exchange _protocol parameters _cryptobox node client dal_node1 = @@ -4107,7 +4121,7 @@ let test_dal_node_gs_invalid_messages_exchange _protocol parameters _cryptobox node client dal_node1 - ~mk_dal_node2:make_invalid_dal_node + ~mk_dal_node2:(make_invalid_dal_node node) ~expect_app_notification ~is_first_slot_attestable @@ -4149,7 +4163,7 @@ let test_gs_prune_and_ihave protocol parameters _cryptobox node client dal_node1 in (* Create another (invalid) DAL node *) - let* dal_node2 = make_invalid_dal_node protocol parameters in + let* _, dal_node2 = make_invalid_dal_node node protocol parameters in (* Connect the nodes *) let* () =