diff --git a/src/bin_dal_node/committee_cache.ml b/src/bin_dal_node/committee_cache.ml index b6d42d02a2bf9fea0461dd7ad936a47bd9a35ebc..3c0ba71a1aaf8be002cb67545a350d778600bc31 100644 --- a/src/bin_dal_node/committee_cache.ml +++ b/src/bin_dal_node/committee_cache.ml @@ -31,9 +31,9 @@ module Level_map = let hash = Hashtbl.hash end) -type shard_indices = {start_index : int; offset : int} +type shard_indexes = int list -type committee = shard_indices Tezos_crypto.Signature.Public_key_hash.Map.t +type committee = shard_indexes Tezos_crypto.Signature.Public_key_hash.Map.t type t = committee Level_map.t diff --git a/src/bin_dal_node/committee_cache.mli b/src/bin_dal_node/committee_cache.mli index db60d32410f2def5912961c38b0345e7df77e706..0fe7d6239d691e1e3994fd7223b9b88f0fdfa094 100644 --- a/src/bin_dal_node/committee_cache.mli +++ b/src/bin_dal_node/committee_cache.mli @@ -27,12 +27,12 @@ type t -(** Represents shard indexes from [start_index] to [start_index + offset - 1]. *) -type shard_indices = {start_index : int; offset : int} +(** Represents shard indexes of an attester. *) +type shard_indexes = int list -(** Represents the committee for a given level, +(** Represents the committee for a given level, as a mapping from an attester to its assigned shard indexes. *) -type committee = shard_indices Tezos_crypto.Signature.Public_key_hash.Map.t +type committee = shard_indexes Tezos_crypto.Signature.Public_key_hash.Map.t (** [create ~max_size] returns an empty cache. If the cache size exceeds [max_size], committees of old [level]s are removed in FIFO order. *) diff --git a/src/bin_dal_node/daemon.ml b/src/bin_dal_node/daemon.ml index 88b6a94f99c940ad6fe933c604082bd3f1da6024..6eebaf439f239346c40816c292c39abc5ac44e35 100644 --- a/src/bin_dal_node/daemon.ml +++ b/src/bin_dal_node/daemon.ml @@ -360,6 +360,20 @@ module Handler = struct Plugin.block_info cctxt ~block ~metadata:`Always in let shell_header = Plugin.block_shell_header block_info in + (* TODO: https://gitlab.com/tezos/tezos/-/issues/6036 + Note that the first processed block is special: in contrast to + the general case, as implemented by this function, the plugin was + set before processing the block, by + [resolve_plugin_and_set_ready], not after processing the + block. *) + let* () = + may_update_plugin + cctxt + ctxt + ~block + ~current_proto:plugin_proto + ~block_proto:shell_header.proto_level + in let*? block_round = Plugin.get_round shell_header.fitness in let* slot_headers = Plugin.get_published_slot_headers block_info in let* () = @@ -428,18 +442,7 @@ module Handler = struct let*! () = Event.(emit layer1_node_final_block (block_level, block_round)) in - (* TODO: https://gitlab.com/tezos/tezos/-/issues/6036 - Note that the first processed block is special: in contrast to - the general case, as implemented by this function, the plugin was - set before processing the block, by - [resolve_plugin_and_set_ready], not after processing the - block. *) - may_update_plugin - cctxt - ctxt - ~block - ~current_proto:plugin_proto - ~block_proto:shell_header.proto_level + return_unit in match last_processed_level with (* TODO: https://gitlab.com/tezos/tezos/-/issues/6849 diff --git a/src/bin_dal_node/node_context.ml b/src/bin_dal_node/node_context.ml index 5cfe529add44257b58f0150b80b4d6d3eec8e3ef..3af1a1a461709c30ba155b004d3f45e522dc05b8 100644 --- a/src/bin_dal_node/node_context.ml +++ b/src/bin_dal_node/node_context.ml @@ -156,11 +156,6 @@ let fetch_committee ctxt ~level = | None -> let*? {plugin = (module Plugin); _} = get_ready ctxt in let+ committee = Plugin.get_committee cctxt ~level in - let committee = - Tezos_crypto.Signature.Public_key_hash.Map.map - (fun (start_index, offset) -> Committee_cache.{start_index; offset}) - committee - in Committee_cache.add cache ~level ~committee ; committee @@ -169,11 +164,7 @@ let fetch_assigned_shard_indices ctxt ~level ~pkh = let+ committee = fetch_committee ctxt ~level in match Tezos_crypto.Signature.Public_key_hash.Map.find pkh committee with | None -> [] - | Some {start_index; offset} -> - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4540 - Consider returning some abstract representation of [(s, n)] - instead of [int list] *) - Stdlib.List.init offset (fun i -> start_index + i) + | Some indexes -> indexes let version {config; _} = let network_name = config.Configuration_file.network_name in diff --git a/src/bin_dal_node/slot_manager.ml b/src/bin_dal_node/slot_manager.ml index 030f8a7056211c9994a1ec6d1b5493ef8ad212ca..214ec26d9d3086468484ac6a2026c315e4820ae2 100644 --- a/src/bin_dal_node/slot_manager.ml +++ b/src/bin_dal_node/slot_manager.ml @@ -146,28 +146,26 @@ let add_commitment_shards ~shards_proofs_precomputation node_store cryptobox let get_opt array i = if i >= 0 && i < Array.length array then Some array.(i) else None -(** [shards_to_attesters committee] takes a committee [Committee_cache.committee] - and returns a function that, given a shard index, yields the pkh of its - attester for that level. *) +module IndexMap = Map.Make (struct + type t = int + + let compare = compare +end) + +(** [shards_to_attesters committee] takes a committee + [Committee_cache.committee] and returns a function that, given a shard + index, yields the pkh of its attester for that level. *) let shards_to_attesters committee = - let rec do_n ~n f acc = if n <= 0 then acc else do_n ~n:(n - 1) f (f acc) in let to_array committee = - (* We transform the map to a list *) - Tezos_crypto.Signature.Public_key_hash.Map.bindings committee - (* We sort the list in decreasing order w.r.t. to start_indices. *) - |> List.fast_sort (fun (_pkh1, shard_indices1) (_pkh2, shard_indices2) -> - shard_indices2.Committee_cache.start_index - - shard_indices1.Committee_cache.start_index) - (* We fold on the sorted list, starting from bigger start_indices. *) - |> List.fold_left - (fun accu (pkh, Committee_cache.{start_index = _; offset}) -> - (* We put in the accu list as many [pkh] occurrences as the number - of shards this pkh should attest, namely, [offset]. *) - do_n ~n:offset (fun acc -> pkh :: acc) accu) - [] - (* We build an array from the list. The array indices coincide with shard - indices. *) - |> Array.of_list + Tezos_crypto.Signature.Public_key_hash.Map.fold + (fun pkh indexes index_map -> + List.fold_left + (fun index_map index -> IndexMap.add index pkh index_map) + index_map + indexes) + committee + IndexMap.empty + |> IndexMap.bindings |> List.map snd |> Array.of_list in let committee = to_array committee in fun index -> get_opt committee index diff --git a/src/bin_dal_node/slot_manager.mli b/src/bin_dal_node/slot_manager.mli index 6bd06a7f88c63f9e1773ddd7e5848311a6552255..8ecc05faa5a00140cace6714e15f74bea7fc26ad 100644 --- a/src/bin_dal_node/slot_manager.mli +++ b/src/bin_dal_node/slot_manager.mli @@ -94,7 +94,7 @@ val add_commitment_shards : val publish_slot_data : level_committee: (level:int32 -> - Committee_cache.shard_indices Signature.Public_key_hash.Map.t tzresult Lwt.t) -> + Committee_cache.shard_indexes Signature.Public_key_hash.Map.t tzresult Lwt.t) -> Store.node_store -> Gossipsub.Worker.t -> Cryptobox.t -> diff --git a/src/lib_dal_node/dal_plugin.ml b/src/lib_dal_node/dal_plugin.ml index 91d51bde6a9dff24fe259a425ac18bc5550043d9..22014dce6d3216900521d0d7c1e26dfef70758b2 100644 --- a/src/lib_dal_node/dal_plugin.ml +++ b/src/lib_dal_node/dal_plugin.ml @@ -67,7 +67,7 @@ module type T = sig val get_committee : Tezos_rpc.Context.generic -> level:int32 -> - (int * int) Tezos_crypto.Signature.Public_key_hash.Map.t tzresult Lwt.t + int list Tezos_crypto.Signature.Public_key_hash.Map.t tzresult Lwt.t val attested_slot_headers : block_info -> number_of_slots:int -> slot_index list tzresult diff --git a/src/lib_dal_node/dal_plugin.mli b/src/lib_dal_node/dal_plugin.mli index 56419401d6e035797c31ba72bf3cee8008b75260..e3fbe4def1b577b80174ca42245ea8eea5ac855d 100644 --- a/src/lib_dal_node/dal_plugin.mli +++ b/src/lib_dal_node/dal_plugin.mli @@ -79,12 +79,11 @@ module type T = sig (** [get_committee ctxt ~level] retrieves the DAL committee at [level] from L1 as a map that associates to the public key hash [pkh] of the member of - the committee an interval [(s,n)], meaning that the slots [s;s+1;...;s+n-1] - belong to [pkh] *) + the committee its assigned shard indexes. *) val get_committee : Tezos_rpc.Context.generic -> level:int32 -> - (int * int) Tezos_crypto.Signature.Public_key_hash.Map.t tzresult Lwt.t + int list Tezos_crypto.Signature.Public_key_hash.Map.t tzresult Lwt.t (** [attested_slot_headers block_info number_of_slots] reads the metadata of the given [block_info] and constructs the list of attested slots diff --git a/src/proto_017_PtNairob/lib_dal/dal_plugin_registration.ml b/src/proto_017_PtNairob/lib_dal/dal_plugin_registration.ml index 1b02684140359b41053543c4c8cb49db7d52dbf4..f5ed9c8f950637394dfb15b8f3b148e24373cadc 100644 --- a/src/proto_017_PtNairob/lib_dal/dal_plugin_registration.ml +++ b/src/proto_017_PtNairob/lib_dal/dal_plugin_registration.ml @@ -110,8 +110,16 @@ module Plugin = struct let+ pkh_to_shards = Plugin.RPC.Dal.dal_shards cpctxt (`Main, `Head 0) ~level () in + let indexes (initial_slot, power) = + let last_slot = initial_slot + power - 1 in + let rec iter acc i = + if i < initial_slot then acc else iter (i :: acc) (i - 1) + in + iter [] last_slot + in List.fold_left - (fun acc (pkh, s) -> Signature.Public_key_hash.Map.add pkh s acc) + (fun acc (pkh, s) -> + Signature.Public_key_hash.Map.add pkh (indexes s) acc) Signature.Public_key_hash.Map.empty pkh_to_shards diff --git a/src/proto_018_Proxford/lib_dal/dal_plugin_registration.ml b/src/proto_018_Proxford/lib_dal/dal_plugin_registration.ml index 8bb2e8072fcfbc3283334d754b468dedecf5a03b..87c820fe7ee11c72e1525b4f228b48365ecbb2fe 100644 --- a/src/proto_018_Proxford/lib_dal/dal_plugin_registration.ml +++ b/src/proto_018_Proxford/lib_dal/dal_plugin_registration.ml @@ -107,8 +107,16 @@ module Plugin = struct let+ pkh_to_shards = Plugin.RPC.Dal.dal_shards cpctxt (`Main, `Head 0) ~level () in + let indexes (initial_slot, power) = + let last_slot = initial_slot + power - 1 in + let rec iter acc i = + if i < initial_slot then acc else iter (i :: acc) (i - 1) + in + iter [] last_slot + in List.fold_left - (fun acc (pkh, s) -> Signature.Public_key_hash.Map.add pkh s acc) + (fun acc (pkh, s) -> + Signature.Public_key_hash.Map.add pkh (indexes s) acc) Signature.Public_key_hash.Map.empty pkh_to_shards diff --git a/src/proto_alpha/lib_dal/dal_plugin_registration.ml b/src/proto_alpha/lib_dal/dal_plugin_registration.ml index 24727e729650d17e8fd5395890a5fff968acea32..3c884f4c45b70c3e2a3cf2b50a46f71b8f971ca7 100644 --- a/src/proto_alpha/lib_dal/dal_plugin_registration.ml +++ b/src/proto_alpha/lib_dal/dal_plugin_registration.ml @@ -108,7 +108,8 @@ module Plugin = struct Plugin.RPC.Dal.dal_shards cpctxt (`Main, `Head 0) ~level () in List.fold_left - (fun acc (pkh, s) -> Signature.Public_key_hash.Map.add pkh s acc) + (fun acc ({delegate; indexes} : Plugin.RPC.Dal.S.shards_assignment) -> + Signature.Public_key_hash.Map.add delegate indexes acc) Signature.Public_key_hash.Map.empty pkh_to_shards diff --git a/src/proto_alpha/lib_parameters/default_parameters.ml b/src/proto_alpha/lib_parameters/default_parameters.ml index 0c86fa36ac1d9d17cdd7576f27b25ed11e85c1f6..84221c87ba73287bbf484d5bda5fa01a8bb00c93 100644 --- a/src/proto_alpha/lib_parameters/default_parameters.ml +++ b/src/proto_alpha/lib_parameters/default_parameters.ml @@ -329,12 +329,7 @@ let constants_sandbox = constants_mainnet.dal with number_of_slots = 16; cryptobox_parameters = - { - Dal.redundancy_factor = 16; - page_size = 4096; - number_of_shards = 2048; - slot_size = 1 lsl 16; - }; + {default_cryptobox_parameters with number_of_shards = 256}; }; issuance_weights; blocks_preservation_cycles = 1; @@ -356,7 +351,7 @@ let constants_sandbox = } let constants_test = - let consensus_committee_size = 25 in + let consensus_committee_size = 67 in let Constants.Generated. {max_slashing_threshold = _; consensus_threshold; issuance_weights} = Constants.Generated.generate ~consensus_committee_size @@ -370,10 +365,9 @@ let constants_test = number_of_slots = 8; cryptobox_parameters = { - redundancy_factor = 16; - page_size = 4096; - number_of_shards = 2048; - slot_size = 1 lsl 16; + default_cryptobox_parameters with + redundancy_factor = 2; + number_of_shards = 64; }; }; issuance_weights; diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index 4ba31406427528a059dbb2b556bae8b8fd1d190b..f937f8b6666c23c0842a0385a43adfffad0f010c 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -3126,21 +3126,42 @@ module Dal = struct ~query RPC_path.(path / "confirmed_slot_headers_history") + type shards_query = { + level : Raw_level.t option; + delegates : Signature.Public_key_hash.t list; + } + let shards_query = - RPC_query.( - query (fun level -> level) - |+ opt_field "level" Raw_level.rpc_arg (fun t -> t) - |> seal) + let open RPC_query in + query (fun level delegates -> {level; delegates}) + |+ opt_field "level" Raw_level.rpc_arg (fun t -> t.level) + |+ multi_field "delegates" Signature.Public_key_hash.rpc_arg (fun t -> + t.delegates) + |> seal + + type shards_assignment = { + delegate : Signature.Public_key_hash.t; + indexes : int list; + } + + let shards_assignment_encoding = + let open Data_encoding in + conv + (fun {delegate; indexes} -> (delegate, indexes)) + (fun (delegate, indexes) -> {delegate; indexes}) + (obj2 + (req "delegate" Signature.Public_key_hash.encoding) + (req "indexes" (list int16))) + + type shards_output = shards_assignment list let shards = RPC_service.get_service ~description: - "Get the shard assignements for a given level (the default is the \ - current level)" + "Get the shards assignment for a given level (the default is the \ + current level) and given delegates (the default is all delegates)" ~query:shards_query - ~output: - Data_encoding.( - list (tup2 Signature.Public_key_hash.encoding (tup2 int16 int16))) + ~output:(Data_encoding.list shards_assignment_encoding) RPC_path.(path / "shards") end @@ -3158,13 +3179,31 @@ module Dal = struct let dal_confirmed_slots_history ctxt block = RPC_context.make_call0 S.dal_confirmed_slot_headers_history ctxt block () () - let dal_shards ctxt block ?level () = - RPC_context.make_call0 S.shards ctxt block level () + let dal_shards ctxt block ?level ?(delegates = []) () = + RPC_context.make_call0 S.shards ctxt block {level; delegates} () let register_shards () = - Registration.register0 ~chunked:true S.shards @@ fun ctxt level () -> - let level = Option.value level ~default:(Level.current ctxt).level in - Dal_services.shards ctxt ~level + Registration.register0 ~chunked:true S.shards @@ fun ctxt q () -> + let open Lwt_result_syntax in + let*? level_opt = + Option.map_e (Level.from_raw_with_offset ctxt ~offset:0l) q.level + in + let level = Option.value level_opt ~default:(Level.current ctxt) in + let* _ctxt, map = Dal_services.shards ctxt ~level in + let query_delegates = Signature.Public_key_hash.Set.of_list q.delegates in + let all_delegates = + Signature.Public_key_hash.Set.is_empty query_delegates + in + Signature.Public_key_hash.Map.fold + (fun delegate indexes acc -> + if + all_delegates + || Signature.Public_key_hash.Set.mem delegate query_delegates + then ({delegate; indexes} : S.shards_assignment) :: acc + else acc) + map + [] + |> return let register () = register_dal_confirmed_slot_headers_history () ; @@ -3883,7 +3922,8 @@ module Attestation_rights = struct consensus_pk = _; consensus_pkh = consensus_key; }, - attestation_power ) + attestation_power, + _dal_power ) acc -> {delegate; consensus_key; first_slot; attestation_power} :: acc) rights diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 3b1211e81d3811bc57918315b4eb0c66be862fa6..8ab973a73d011edd39f2c4bb1043dc9c0849bbb8 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -80,6 +80,8 @@ module Slot : sig val succ : t -> t tzresult + val to_int : t -> int + val of_int_do_not_use_except_for_parameters : int -> t val encoding : t Data_encoding.encoding @@ -2733,6 +2735,8 @@ module Dal : sig val number_of_slots : context -> int + val number_of_shards : context -> int + (** This module re-exports definitions from {!Dal_slot_index_repr}. *) module Slot_index : sig type t @@ -2785,20 +2789,7 @@ module Dal : sig val expected_size_in_bits : max_index:Slot_index.t -> int - val power_of_attester : context -> attester:public_key_hash -> int option - val record_number_of_attested_shards : context -> t -> int -> context - - type committee = { - pkh_to_shards : (shard_index * int) Signature.Public_key_hash.Map.t; - } - - val compute_committee : - context -> - (Slot.t -> (context * Signature.Public_key_hash.t) tzresult Lwt.t) -> - committee tzresult Lwt.t - - val init_committee : context -> committee -> context end type slot_id = {published_level : Raw_level.t; index : Slot_index.t} @@ -2975,6 +2966,7 @@ module Dal_errors : sig | Dal_data_availibility_attester_not_in_committee of { attester : Signature.Public_key_hash.t; level : Raw_level.t; + slot : Slot.t; } | Dal_cryptobox_error of {explanation : string} end diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 414ca479208a3ec919c0aaadfb94e0c7a7ab2044..461cc5673b60936d18b0aaa3c3f79d07e8025719 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2237,7 +2237,8 @@ let find_in_slot_map slot slot_map = | None -> (* This should not happen: operation validation should have failed. *) tzfail Faulty_validation_wrong_slot - | Some (consensus_key, power) -> return (consensus_key, power)) + | Some (consensus_key, power, dal_power) -> + return (consensus_key, power, dal_power)) let record_preattestation ctxt (mode : mode) (content : consensus_content) : (context * Kind.preattestation contents_result_list) tzresult Lwt.t = @@ -2263,7 +2264,7 @@ let record_preattestation ctxt (mode : mode) (content : consensus_content) : in match mode with | Application _ | Full_construction _ -> - let*? consensus_key, power = + let*? consensus_key, power, _dal_power = find_in_slot_map content.slot (Consensus.allowed_preattestations ctxt) in let*? ctxt = @@ -2305,7 +2306,7 @@ let record_attestation ctxt (mode : mode) (consensus : consensus_content) in match mode with | Application _ | Full_construction _ -> - let*? consensus_key, power = + let*? consensus_key, power, dal_power = find_in_slot_map consensus.slot (Consensus.allowed_attestations ctxt) in let*? ctxt = @@ -2315,11 +2316,7 @@ let record_attestation ctxt (mode : mode) (consensus : consensus_content) Option.fold ~none:(Result_syntax.return ctxt) ~some:(fun dal -> - Dal_apply.apply_attestation - ctxt - consensus_key - consensus.level - dal.attestation) + Dal_apply.apply_attestation ctxt dal.attestation ~power:dal_power) dal in return (ctxt, mk_attestation_result consensus_key power) @@ -2788,7 +2785,9 @@ let record_attesting_participation ctxt = | None -> tzfail (Consensus.Slot_map_not_found {loc = __LOC__}) | Some validators -> Slot.Map.fold_es - (fun initial_slot ((consensus_pk : Consensus_key.pk), power) ctxt -> + (fun initial_slot + ((consensus_pk : Consensus_key.pk), power, _dal_power) + ctxt -> let participation = if Slot.Set.mem initial_slot (Consensus.attestations_seen ctxt) then Delegate.Participated diff --git a/src/proto_alpha/lib_protocol/baking.ml b/src/proto_alpha/lib_protocol/baking.ml index 2bff27b7289e83843dc8328b7a459cffc0fd56b5..7cc21c60edc0083babdcb119e14b19cb7554d235 100644 --- a/src/proto_alpha/lib_protocol/baking.ml +++ b/src/proto_alpha/lib_protocol/baking.ml @@ -110,6 +110,7 @@ let attesting_rights_by_first_slot ctxt level = let*? slots = Slot.Range.create ~min:0 ~count:(Constants.consensus_committee_size ctxt) in + let number_of_shards = Dal.number_of_shards ctxt in let* ctxt, (_, slots_map) = Slot.Range.fold_es (fun (ctxt, (delegates_map, slots_map)) slot -> @@ -132,12 +133,16 @@ let attesting_rights_by_first_slot ctxt level = in (* [slots_map]'keys are the minimal slots of delegates because we fold on slots in increasing order *) + let in_dal_committee = + if Compare.Int.(Slot.to_int slot < number_of_shards) then 1 else 0 + in let slots_map = Slot.Map.update initial_slot (function - | None -> Some (consensus_pk, 1) - | Some (consensus_pk, count) -> Some (consensus_pk, count + 1)) + | None -> Some (consensus_pk, 1, in_dal_committee) + | Some (consensus_pk, count, dal_count) -> + Some (consensus_pk, count + 1, dal_count + in_dal_committee)) slots_map in (ctxt, (delegates_map, slots_map))) diff --git a/src/proto_alpha/lib_protocol/baking.mli b/src/proto_alpha/lib_protocol/baking.mli index d99e7b9dab7b4a5d89f1574b90ca5bf3e5a6b301..0aeabf4f5731ba478fe17c2641597f85881caacf 100644 --- a/src/proto_alpha/lib_protocol/baking.mli +++ b/src/proto_alpha/lib_protocol/baking.mli @@ -53,12 +53,12 @@ val attesting_rights : (** Computes attesting rights for a given level. - @return map from allocated first slots to their owner's public key, public key - hash, and attesting power. *) + @return map from allocated first slots to their owner's public key, consensus + attesting power, and DAL attesting power. *) val attesting_rights_by_first_slot : context -> Level.t -> - (context * (Consensus_key.pk * int) Slot.Map.t) tzresult Lwt.t + (context * (Consensus_key.pk * int * int) Slot.Map.t) tzresult Lwt.t (** Computes the bonus baking reward depending on the attestation power. *) val bonus_baking_reward : context -> attestation_power:int -> Tez.t tzresult diff --git a/src/proto_alpha/lib_protocol/dal_apply.ml b/src/proto_alpha/lib_protocol/dal_apply.ml index 4ea774778029370577824613745075c77af6a05b..c3c5b1aa16fc7e41175c7ae1d0c78142caf6a3e4 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.ml +++ b/src/proto_alpha/lib_protocol/dal_apply.ml @@ -53,7 +53,7 @@ let slot_of_int_e ~number_of_slots n = let pkh_of_consensus_key (consensus_key : Consensus_key.pk) = consensus_key.delegate -let validate_block_attestation ctxt level consensus_key attestation = +let validate_attestation ctxt level slot consensus_key attestation = let open Lwt_result_syntax in let*? () = assert_dal_feature_enabled ctxt in let number_of_slots = Dal.number_of_slots ctxt in @@ -65,36 +65,17 @@ let validate_block_attestation ctxt level consensus_key attestation = Compare.Int.(size <= maximum_size) (Dal_attestation_size_limit_exceeded {maximum_size; got = size}) in - let attester = pkh_of_consensus_key consensus_key in + let number_of_shards = Dal.number_of_shards ctxt in fail_when - (Option.is_none @@ Dal.Attestation.power_of_attester ctxt ~attester) - (Dal_data_availibility_attester_not_in_committee {attester; level}) + Compare.Int.(Slot.to_int slot >= number_of_shards) + (let attester = pkh_of_consensus_key consensus_key in + Dal_data_availibility_attester_not_in_committee {attester; level; slot}) -let validate_mempool_attestation ctxt attestation = - let open Lwt_result_syntax in - let*? () = assert_dal_feature_enabled ctxt in - let number_of_slots = Dal.number_of_slots ctxt in - let*? max_index = number_of_slots - 1 |> slot_of_int_e ~number_of_slots in - let maximum_size = Dal.Attestation.expected_size_in_bits ~max_index in - let size = Dal.Attestation.occupied_size_in_bits attestation in - fail_unless - Compare.Int.(size <= maximum_size) - (Dal_attestation_size_limit_exceeded {maximum_size; got = size}) - -let apply_attestation ctxt consensus_key level attestation = +let apply_attestation ctxt attestation ~power = let open Result_syntax in let* () = assert_dal_feature_enabled ctxt in - let attester = pkh_of_consensus_key consensus_key in - match Dal.Attestation.power_of_attester ctxt ~attester with - | None -> - (* This should not happen: operation validation should have failed. *) - error (Dal_data_availibility_attester_not_in_committee {attester; level}) - | Some power -> - return - (Dal.Attestation.record_number_of_attested_shards - ctxt - attestation - power) + return + (Dal.Attestation.record_number_of_attested_shards ctxt attestation power) (* This function should fail if we don't want the operation to be propagated over the L1 gossip network. Because this is a manager @@ -149,23 +130,3 @@ let finalisation ctxt = Dal.Slot.finalize_pending_slot_headers ctxt ~number_of_slots in (ctxt, attestation)) - -let compute_committee ctxt level = - let open Lwt_result_syntax in - let*? () = assert_dal_feature_enabled ctxt in - let pkh_from_tenderbake_slot slot = - let+ ctxt, consensus_key = Stake_distribution.slot_owner ctxt level slot in - (ctxt, pkh_of_consensus_key consensus_key) - in - Alpha_context.Dal.Attestation.compute_committee ctxt pkh_from_tenderbake_slot - -let initialisation ctxt ~level = - let open Lwt_result_syntax in - only_if_dal_feature_enabled - ctxt - ~default:(fun ctxt -> return ctxt) - (fun ctxt -> - let+ committee = compute_committee ctxt level in - (* This committee is cached because it is the one we will use - for the validation of the DAL attestations. *) - Alpha_context.Dal.Attestation.init_committee ctxt committee) diff --git a/src/proto_alpha/lib_protocol/dal_apply.mli b/src/proto_alpha/lib_protocol/dal_apply.mli index b7da86a8bb472469412212b6ffe8d61162ee2723..55bd78051f1a89805bdb6188d641cdd75e68b9a1 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.mli +++ b/src/proto_alpha/lib_protocol/dal_apply.mli @@ -28,37 +28,27 @@ open Alpha_context -(** [validate_block_attestation ctxt level consensus_key attestation] checks +(** [validate_attestation ctxt level slot consensus_key attestation] checks whether the DAL attestation [attestation] emitted at given [level] by the - attester with the given [consensus_key] is valid for block inclusion. If an + attester with the given [consensus_key] and given [slot] is valid. If an [Error _] is returned, the [op] is not valid. The checks made are: * the attestation size does not exceed the maximum; * the delegate is in the DAL committee. These are checks done for the DAL part alone, checks on other fields of an - attestation (like level, round, slot) are done by the caller. *) -val validate_block_attestation : + attestation (like level, round) are done by the caller. *) +val validate_attestation : t -> Raw_level.t -> + Slot.t -> Consensus_key.pk -> Dal.Attestation.t -> unit tzresult Lwt.t -(** [validate_mempool_attestation ctxt level consensus_key attestation] checks - whether the DAL attestation [attestation] is valid for the mempool. It is - similar to [check_block_attestion], but it performs only the check on the - size, as [consensus_key] is not available. If an [Error _] is returned, the - [op] is not valid. - - These are checks done for the DAL part alone, checks on other fields of an - attestation (like level, round, slot) are done by the caller. *) -val validate_mempool_attestation : t -> Dal.Attestation.t -> unit tzresult Lwt.t - -(** [apply_attestation ctxt consensus_key level attestation] applies - [attestation] into the [ctxt] assuming [consensus_key.delegate] issued those - attestations at level [level]. *) -val apply_attestation : - t -> Consensus_key.pk -> Raw_level.t -> Dal.Attestation.t -> t tzresult +(** [apply_attestation ctxt attestation] records in the context that the given + [attestation] was issued and the corresponding attester has the given + [power]. *) +val apply_attestation : t -> Dal.Attestation.t -> power:int -> t tzresult (** [validate_publish_commitment ctxt slot] ensures that [slot_header] is valid and prevents an operation containing [slot_header] to be @@ -80,12 +70,3 @@ val apply_publish_commitment : [lag] is a parametric constant specific to the data-availability layer. *) val finalisation : t -> (t * Dal.Attestation.t) tzresult Lwt.t - -(** [initialize ctxt ~level] should be executed at block - initialisation time. It allows to cache the committee for [level] - in memory so that every time we need to use this committee, there - is no need to recompute it again. *) -val initialisation : t -> level:Level.t -> t tzresult Lwt.t - -(** [compute_committee ctxt level] computes the DAL committee for [level]. *) -val compute_committee : t -> Level.t -> Dal.Attestation.committee tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/dal_errors_repr.ml b/src/proto_alpha/lib_protocol/dal_errors_repr.ml index dd62bf25d8e7143b68583ed3338a4ff68fdf27c2..585b9b6f78ccec0e2961c1be9291fe281925944f 100644 --- a/src/proto_alpha/lib_protocol/dal_errors_repr.ml +++ b/src/proto_alpha/lib_protocol/dal_errors_repr.ml @@ -42,6 +42,7 @@ type error += | Dal_data_availibility_attester_not_in_committee of { attester : Signature.Public_key_hash.t; level : Raw_level_repr.t; + slot : Slot_repr.t; } | Dal_cryptobox_error of {explanation : string} | Dal_register_invalid_slot_header of { @@ -186,24 +187,29 @@ let () = ~id:"Dal_data_availibility_attester_not_in_committee" ~title:"The attester is not part of the DAL committee for this level" ~description:"The attester is not part of the DAL committee for this level" - ~pp:(fun ppf (attester, level) -> + ~pp:(fun ppf (attester, level, slot) -> Format.fprintf ppf - "The attester %a is not part of the DAL committee for the level %a" + "The attester %a, with slot %a, is not part of the DAL committee for \ + the level %a." Signature.Public_key_hash.pp attester + Slot_repr.pp + slot Raw_level_repr.pp level) Data_encoding.( - obj2 + obj3 (req "attester" Signature.Public_key_hash.encoding) - (req "level" Raw_level_repr.encoding)) + (req "level" Raw_level_repr.encoding) + (req "slot" Slot_repr.encoding)) (function - | Dal_data_availibility_attester_not_in_committee {attester; level} -> - Some (attester, level) + | Dal_data_availibility_attester_not_in_committee {attester; level; slot} + -> + Some (attester, level, slot) | _ -> None) - (fun (attester, level) -> - Dal_data_availibility_attester_not_in_committee {attester; level}) ; + (fun (attester, level, slot) -> + Dal_data_availibility_attester_not_in_committee {attester; level; slot}) ; register_error_kind `Permanent ~id:"dal_cryptobox_error" diff --git a/src/proto_alpha/lib_protocol/dal_services.ml b/src/proto_alpha/lib_protocol/dal_services.ml index 038e980885f4076fa9f58d2faa7b84b3f6c48e0b..1668c2f1b40a281290d7e9c0656ab24653d279ed 100644 --- a/src/proto_alpha/lib_protocol/dal_services.ml +++ b/src/proto_alpha/lib_protocol/dal_services.ml @@ -32,12 +32,23 @@ let assert_dal_feature_enabled ctxt = Compare.Bool.(feature_enable = true) Dal_errors.Dal_feature_disabled +(* Slots returned by this function are assumed by consumers to be in increasing + order, hence the use of [Slot.Range.rev_fold_es]. *) let shards ctxt ~level = let open Lwt_result_syntax in - let open Dal.Attestation in let*? () = assert_dal_feature_enabled ctxt in - let level = Level.from_raw ctxt level in - (* We do not cache this committee. This function being used by RPCs - to know the DAL committee at some particular level. *) - let+ committee = Dal_apply.compute_committee ctxt level in - Signature.Public_key_hash.Map.bindings committee.pkh_to_shards + let number_of_shards = Dal.number_of_shards ctxt in + let*? slots = Slot.Range.create ~min:0 ~count:number_of_shards in + Slot.Range.rev_fold_es + (fun (ctxt, map) slot -> + let* ctxt, consensus_pk = Stake_distribution.slot_owner ctxt level slot in + let slot = Slot.to_int slot in + let map = + Signature.Public_key_hash.Map.update + consensus_pk.delegate + (function None -> Some [slot] | Some slots -> Some (slot :: slots)) + map + in + return (ctxt, map)) + (ctxt, Signature.Public_key_hash.Map.empty) + slots diff --git a/src/proto_alpha/lib_protocol/dal_services.mli b/src/proto_alpha/lib_protocol/dal_services.mli index d6394f128decf75158f7871bf0b034b09ea36af6..25d8803106af2fb56b104a6714176dd3797cad5f 100644 --- a/src/proto_alpha/lib_protocol/dal_services.mli +++ b/src/proto_alpha/lib_protocol/dal_services.mli @@ -23,11 +23,10 @@ (* *) (*****************************************************************************) -(** [shards ctxt ~level] returns the DAL committee as an association - list that associates to the public key hash [pkh] of the member of - the committee an interval [(s,n)], meaning that the slots - [s;s+1;...;s+n-1] belongs to [pkh]. It is guaranteed that [n>0]. *) +(** [shards ctxt ~level] returns the DAL committee as a mapping from the public + key hash of members of the committee to the list of shard indexes associated + to that member. *) val shards : Alpha_context.t -> - level:Alpha_context.Raw_level.t -> - (Signature.Public_key_hash.t * (int * int)) list tzresult Lwt.t + level:Alpha_context.Level.t -> + (Alpha_context.t * int list Signature.Public_key_hash.Map.t) tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/main.ml b/src/proto_alpha/lib_protocol/main.ml index 5583e2b9bac06fe6fa836655cfd4d908c434084d..be4b1afce84ac609ab1ecfea1330fd88aab3b640 100644 --- a/src/proto_alpha/lib_protocol/main.ml +++ b/src/proto_alpha/lib_protocol/main.ml @@ -223,7 +223,6 @@ let prepare_ctxt ctxt mode ~(predecessor : Block_header.shell_header) = | Partial_construction _ -> init_consensus_rights_for_mempool ctxt ~predecessor_level in - let* ctxt = Dal_apply.initialisation ~level:predecessor_level ctxt in return ( ctxt, migration_balance_updates, diff --git a/src/proto_alpha/lib_protocol/raw_context.ml b/src/proto_alpha/lib_protocol/raw_context.ml index b0fe9d38b8fcdb384cd66da7d8a591814f580ccc..9ccc46907926b0d73662dc9ba0b40a8ce915f452 100644 --- a/src/proto_alpha/lib_protocol/raw_context.ml +++ b/src/proto_alpha/lib_protocol/raw_context.ml @@ -87,18 +87,19 @@ module Raw_consensus = struct type t = { current_attestation_power : int; (** Number of attestation slots recorded for the current block. *) - allowed_attestations : (consensus_pk * int) Slot_repr.Map.t option; - (** Attestations rights for the current block. Only an attestation - for the lowest slot in the block can be recorded. The map - associates to each initial slot the [pkh] associated to this - slot with its power. This is [None] only in mempool mode. *) - allowed_preattestations : (consensus_pk * int) Slot_repr.Map.t option; + allowed_attestations : (consensus_pk * int * int) Slot_repr.Map.t option; + (** Attestations rights for the current block. Only an attestation for + the lowest slot in the block can be recorded. The map associates to + each initial slot the [pkh] associated to this slot with its + consensus attestation power and DAL attestation power. This is + [None] only in mempool mode. *) + allowed_preattestations : (consensus_pk * int * int) Slot_repr.Map.t option; (** Preattestations rights for the current block. Only a preattestation - for the lowest slot in the block can be recorded. The map - associates to each initial slot the [pkh] associated to this - slot with its power. This is [None] only in mempool mode, or in - application mode when there is no locked round (so the block - cannot contain any preattestations). *) + for the lowest slot in the block can be recorded. The map associates + to each initial slot the [pkh] associated to this slot with its + consensus attestation power and DAL attestation power. This is + [None] only in mempool mode, or in application mode when there is no + locked round (so the block cannot contain any preattestations). *) forbidden_delegates : Signature.Public_key_hash.Set.t; (** Delegates that are not allowed to bake or attest blocks; i.e., delegates which have zero frozen deposit due to a previous @@ -222,13 +223,6 @@ module Raw_consensus = struct {t with attestation_branch = Some attestation_branch} end -type dal_committee = { - pkh_to_shards : - (Dal_attestation_repr.shard_index * int) Signature.Public_key_hash.Map.t; -} - -let empty_dal_committee = {pkh_to_shards = Signature.Public_key_hash.Map.empty} - type back = { context : Context.t; constants : Constants_parametric_repr.t; @@ -267,7 +261,6 @@ type back = { - We need to provide an incentive to avoid byzantines to post dummy slot headers. *) dal_attestation_slot_accountability : Dal_attestation_repr.Accountability.t; - dal_committee : dal_committee; dal_cryptobox : Dal.t option; adaptive_issuance_enable : bool; } @@ -883,7 +876,6 @@ let prepare ~level ~predecessor_timestamp ~timestamp ~adaptive_issuance_enable Dal_attestation_repr.Accountability.init ~number_of_slots: constants.Constants_parametric_repr.dal.number_of_slots; - dal_committee = empty_dal_committee; dal_cryptobox = None; adaptive_issuance_enable; }; @@ -1672,9 +1664,9 @@ module type CONSENSUS = sig type consensus_pk - val allowed_attestations : t -> (consensus_pk * int) slot_map option + val allowed_attestations : t -> (consensus_pk * int * int) slot_map option - val allowed_preattestations : t -> (consensus_pk * int) slot_map option + val allowed_preattestations : t -> (consensus_pk * int * int) slot_map option val forbidden_delegates : t -> Signature.Public_key_hash.Set.t @@ -1684,8 +1676,8 @@ module type CONSENSUS = sig val initialize_consensus_operation : t -> - allowed_attestations:(consensus_pk * int) slot_map option -> - allowed_preattestations:(consensus_pk * int) slot_map option -> + allowed_attestations:(consensus_pk * int * int) slot_map option -> + allowed_preattestations:(consensus_pk * int * int) slot_map option -> t val record_attestation : t -> initial_slot:slot -> power:int -> t tzresult @@ -1829,6 +1821,9 @@ module Dal = struct let number_of_slots ctxt = ctxt.back.constants.dal.number_of_slots + let number_of_shards ctxt = + ctxt.back.constants.dal.cryptobox_parameters.number_of_shards + let record_number_of_attested_shards ctxt attestation number = let dal_attestation_slot_accountability = Dal_attestation_repr.Accountability.record_number_of_attested_shards @@ -1873,94 +1868,6 @@ module Dal = struct ctxt.back.dal_attestation_slot_accountability ~threshold ~number_of_shards - - type committee = dal_committee = { - pkh_to_shards : - (Dal_attestation_repr.shard_index * int) Signature.Public_key_hash.Map.t; - } - - (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3110 - - A committee is selected by the callback function - [pkh_from_tenderbake_slot]. We use a callback because of circular - dependencies. It is not clear whether it will be the final choice - for the DAL committee. The current solution is a bit hackish but - should work. If we decide to differ from the Tenderbake - committee, one could just draw a new committee. - - The problem with drawing a new committee is that it is not - guaranteed that everyone in the DAL committee will be in the - Tenderbake committee. Consequently, either we decide to have a - new consensus operation which does not count for Tenderbake, - and/or we take into account for the model of DAL that at every - level, a percentage of DAL attestations cannot be received. *) - let compute_committee ctxt pkh_from_tenderbake_slot = - let open Lwt_result_syntax in - let Constants_parametric_repr. - { - dal = {cryptobox_parameters = {number_of_shards; _}; _}; - consensus_committee_size; - _; - } = - ctxt.back.constants - in - (* We first draw a committee by drawing slots from the Tenderbake - committee. To have a compact representation of slots, we can - sort the Tenderbake slots by [pkh], so that a committee is - actually only an interval. This is done by recomputing a - committee from the first one. *) - let update_committee committee pkh ~slot_index ~power = - { - pkh_to_shards = - Signature.Public_key_hash.Map.update - pkh - (function - | None -> Some (slot_index, power) - | Some (initial_shard_index, old_power) -> - Some (initial_shard_index, old_power + power)) - committee.pkh_to_shards; - } - in - let rec compute_power index committee = - if Compare.Int.(index < 0) then return committee - else - let shard_index = index mod consensus_committee_size in - let*? slot = Slot_repr.of_int shard_index in - let* _ctxt, pkh = pkh_from_tenderbake_slot slot in - (* The [Slot_repr] module is related to the Tenderbake committee. *) - let slot_index = Slot_repr.to_int slot in - let committee = update_committee committee pkh ~slot_index ~power:1 in - compute_power (index - 1) committee - in - (* This committee is an intermediate to compute the final DAL - committee. This one only projects the Tenderbake committee into - the DAL committee. The next one reorders the slots so that they - are grouped by public key hash. *) - let* unordered_committee = - compute_power (number_of_shards - 1) empty_dal_committee - in - let dal_committee = - Signature.Public_key_hash.Map.fold - (fun pkh (_, power) (total_power, committee) -> - let committee = - update_committee committee pkh ~slot_index:total_power ~power - in - let new_total_power = total_power + power in - (new_total_power, committee)) - unordered_committee.pkh_to_shards - (0, empty_dal_committee) - |> snd - in - return dal_committee - - let init_committee ctxt committee = - {ctxt with back = {ctxt.back with dal_committee = committee}} - - let power_of_attester ctxt ~attester:pkh = - Signature.Public_key_hash.Map.find_opt - pkh - ctxt.back.dal_committee.pkh_to_shards - |> Option.map snd end (* The type for relative context accesses instead from the root. In order for diff --git a/src/proto_alpha/lib_protocol/raw_context.mli b/src/proto_alpha/lib_protocol/raw_context.mli index a6fc18439b4f940849481eb9cfd373adb6707174..8ce1fbe2de0437ec2792f5037ff085ba1642b9f9 100644 --- a/src/proto_alpha/lib_protocol/raw_context.mli +++ b/src/proto_alpha/lib_protocol/raw_context.mli @@ -328,15 +328,13 @@ module type CONSENSUS = sig type consensus_pk - (** Returns a map where each attester's pkh is associated to the - list of its attesting slots (in decreasing order) for a given - level. *) - val allowed_attestations : t -> (consensus_pk * int) slot_map option + (** Returns a map where from the initial slot of each attester in the TB + committee for a given level, to the attester's public key and its + consensus power and DAL power. *) + val allowed_attestations : t -> (consensus_pk * int * int) slot_map option - (** Returns a map where each attester's pkh is associated to the - list of its attesting slots (in decreasing order) for a given - level. *) - val allowed_preattestations : t -> (consensus_pk * int) slot_map option + (** See {!allowed_attestations}. *) + val allowed_preattestations : t -> (consensus_pk * int * int) slot_map option (** Returns the set of delegates that are not allowed to bake or attest blocks; i.e., delegates which have zero frozen deposit @@ -355,8 +353,8 @@ module type CONSENSUS = sig operation. *) val initialize_consensus_operation : t -> - allowed_attestations:(consensus_pk * int) slot_map option -> - allowed_preattestations:(consensus_pk * int) slot_map option -> + allowed_attestations:(consensus_pk * int * int) slot_map option -> + allowed_preattestations:(consensus_pk * int * int) slot_map option -> t (** [record_attestation ctx ~initial_slot ~power] records an @@ -433,6 +431,8 @@ module Dal : sig val number_of_slots : t -> int + val number_of_shards : t -> int + (** [record_number_of_attested_shards ctxt attestation number_of_shards] records that the [number_of_shards] shards were attested (declared available by some attester). *) @@ -455,43 +455,4 @@ module Dal : sig otherwise. If the [index] is out of the interval [0;number_of_slots - 1], returns [false]. *) val is_slot_index_attested : t -> Dal_slot_index_repr.t -> bool - - (** [power_of_attester ctxt ~attester] returns the number of shards assigned - to [attester] at the current level. It never returns [Some 0]. Instead, it - returns [None] if the attester is not in the DAL committee. *) - val power_of_attester : - t -> attester:Signature.Public_key_hash.t -> int option - - (** The DAL committee is a subset of the Tenderbake committee. A - shard from [0; number_of_shards - 1] is associated to a public key - hash. The committee is a mapping from public key hashes to shards and - The DAL committee ensures the shards associated to the - same public key hash are contiguous. The list of shards is - represented as two natural numbers [(initial, power)] which - encodes the list of shards: - [initial; initial + 1; ... ; initial + power - 1]. *) - type committee = { - pkh_to_shards : - (Dal_attestation_repr.shard_index * int) Signature.Public_key_hash.Map.t; - } - - (** [compute_committee ctxt pkh_from_tenderbake_slot] computes the - DAL committee using the [pkh_from_tenderbake_slot] function. This - functions takes into account the fact that the DAL committee and - the Tenderbake committee may have different sizes. If the DAL - committee is smaller, then we simply take a projection of the - Tenderbake committee for the first [n] slots. If the DAL - committee is larger, shards are computed modulo the Tenderbake - committee. Slots assignments are reordered for a given a public - key hash to ensure all the slots (or shards in the context of - DAL) shards are contiguous (see {!type:committee}). *) - val compute_committee : - t -> - (Slot_repr.t -> (t * Signature.Public_key_hash.t) tzresult Lwt.t) -> - committee tzresult Lwt.t - - (** [init_committee ctxt committee] returns a context where the - [committee] is cached. The committee is expected to be the one - for the current level. *) - val init_committee : t -> committee -> t end diff --git a/src/proto_alpha/lib_protocol/test/helpers/context.mli b/src/proto_alpha/lib_protocol/test/helpers/context.mli index 05737069baf78d1b74c3f890445426dd5cdd0389..67429874ad712c7bf7de84e03e03bfba0e0c0fd7 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/context.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/context.mli @@ -199,8 +199,9 @@ module Dal : sig val shards : t -> ?level:Raw_level.t -> + ?delegates:Signature.public_key_hash list -> unit -> - (Signature.Public_key_hash.t * (int * int)) list tzresult Lwt.t + Plugin.RPC.Dal.S.shards_output tzresult Lwt.t end module Contract : sig diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_attestation.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_attestation.ml index d3d30db6a04bf9869c61befa9f52b3ee0d4128fc..6882d56aa94ff65d0667ac8d2d77fbef5364e8c4 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_attestation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_attestation.ml @@ -725,7 +725,10 @@ let test_attester_not_in_dal_committee () = committee in let in_dal_committee = - List.mem_assoc ~equal:Signature.Public_key_hash.equal pkh dal_committee + List.exists + (fun ({delegate; _} : Plugin.RPC.Dal.S.shards_assignment) -> + Signature.Public_key_hash.equal pkh delegate) + dal_committee in if in_committee && not in_dal_committee then let dal_content = {attestation = Dal.Attestation.empty} in @@ -736,7 +739,7 @@ let test_attester_not_in_dal_committee () = Environment.Ecoproto_error (Alpha_context.Dal_errors .Dal_data_availibility_attester_not_in_committee - {attester; level}); + {attester; level; slot = _}); ] when Signature.Public_key_hash.equal attester pkh && Raw_level.to_int32 level = b.header.shell.level -> @@ -797,10 +800,11 @@ let test_dal_attestation_threshold () = Log.info "Number of minimum required attested shards: %d" min_power ; let* _ = List.fold_left_es - (fun (acc_ops, acc_power) (pkh, (_first_index, power)) -> - let* op = Op.attestation ~delegate:pkh ~dal_content b in + (fun (acc_ops, acc_power) + ({delegate; indexes} : RPC.Dal.S.shards_assignment) -> + let* op = Op.attestation ~delegate ~dal_content b in let ops = op :: acc_ops in - let power = acc_power + power in + let power = acc_power + List.length indexes in let* _b, (metadata, _ops) = Block.bake_with_metadata ~operations:ops b in diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 6775bf626eb6bd5d6632319c64c227299cd18e95..7915e67fe1dbc24a20c37ed2ff49e70c5e9e47e2 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -29,8 +29,8 @@ open Alpha_context type consensus_info = { predecessor_level : Raw_level.t; predecessor_round : Round.t; - preattestation_slot_map : (Consensus_key.pk * int) Slot.Map.t option; - attestation_slot_map : (Consensus_key.pk * int) Slot.Map.t option; + preattestation_slot_map : (Consensus_key.pk * int * int) Slot.Map.t option; + attestation_slot_map : (Consensus_key.pk * int * int) Slot.Map.t option; } let init_consensus_info ctxt (predecessor_level, predecessor_round) = @@ -505,7 +505,7 @@ module Consensus = struct let*? () = check_round kind locked_round round in let expected_payload_hash = block_info.header_contents.payload_hash in let*? () = check_payload_hash kind expected_payload_hash bph in - let*? consensus_key, voting_power = + let*? consensus_key, voting_power, _dal_power = get_delegate_details consensus_info.preattestation_slot_map kind slot in return (consensus_key, voting_power) @@ -533,7 +533,7 @@ module Consensus = struct however check that all preattestations have the same round in [check_construction_preattestation_round_consistency] further below. *) let*? () = check_payload_hash kind expected_payload_hash bph in - let*? consensus_key, voting_power = + let*? consensus_key, voting_power, _dal_power = get_delegate_details consensus_info.preattestation_slot_map kind slot in return (consensus_key, voting_power) @@ -697,10 +697,11 @@ module Consensus = struct (** Attestation checks for all modes that involve a block: Application, Partial_validation, and Construction. + Checks regarding the DAL content are done separately. Return the slot owner's consensus key and voting power. *) let check_block_attestation vi consensus_info - {level; round; block_payload_hash = bph; slot} dal_content_opt = + {level; round; block_payload_hash = bph; slot} = let open Lwt_result_syntax in let*? expected_payload_hash = match Consensus.attestation_branch vi.ctxt with @@ -717,20 +718,9 @@ module Consensus = struct let*? () = check_level kind consensus_info.predecessor_level level in let*? () = check_round kind consensus_info.predecessor_round round in let*? () = check_payload_hash kind expected_payload_hash bph in - let*? consensus_key, voting_power = + let*? consensus_key, voting_power, _dal_power = get_delegate_details consensus_info.attestation_slot_map kind slot in - let* () = - Option.fold - ~none:return_unit - ~some:(fun dal -> - Dal_apply.validate_block_attestation - vi.ctxt - level - consensus_key - dal.attestation) - dal_content_opt - in return (consensus_key, voting_power) let check_attestation vi ~check_signature @@ -747,19 +737,8 @@ module Consensus = struct let* consensus_key, voting_power = match vi.mode with | Application _ | Partial_validation _ | Construction _ -> - check_block_attestation - vi - consensus_info - consensus_content - dal_content + check_block_attestation vi consensus_info consensus_content | Mempool -> - let* () = - Option.fold - ~none:return_unit - ~some:(fun dal -> - Dal_apply.validate_mempool_attestation vi.ctxt dal.attestation) - dal_content - in check_mempool_consensus vi consensus_info @@ -767,6 +746,18 @@ module Consensus = struct consensus_content in let* () = check_delegate_is_not_forbidden vi.ctxt consensus_key.delegate in + let* () = + Option.fold + ~none:return_unit + ~some:(fun dal -> + Dal_apply.validate_attestation + vi.ctxt + consensus_content.level + consensus_content.slot + consensus_key + dal.attestation) + dal_content + in let*? () = if check_signature then Operation.check_signature diff --git a/tezt/lib_tezos/RPC.ml b/tezt/lib_tezos/RPC.ml index c8d2919259e8842a68801b740dfc53977669eeb4..0a48f5217d4052b515c2c8913e68641d820af20f 100644 --- a/tezt/lib_tezos/RPC.ml +++ b/tezt/lib_tezos/RPC.ml @@ -1670,11 +1670,10 @@ let get_chain_block_votes_total_voting_power ?(chain = "main") ?(block = "head") Fun.id let get_chain_block_context_dal_shards ?(chain = "main") ?(block = "head") - ?level () = + ?level ?delegates () = let query_string = - match level with - | None -> [] - | Some level -> [("level", string_of_int level)] + Query_arg.opt_list "delegates" (fun x y -> (x, y)) delegates + @ Query_arg.opt "level" Int.to_string level in make GET diff --git a/tezt/lib_tezos/RPC.mli b/tezt/lib_tezos/RPC.mli index 299078846baeb18e31349ee23d708f2efbb7525e..29aa9029306df074dd2d7157ecf1fcf402fbf867 100644 --- a/tezt/lib_tezos/RPC.mli +++ b/tezt/lib_tezos/RPC.mli @@ -1313,9 +1313,17 @@ val get_chain_block_votes_successor_period : val get_chain_block_votes_total_voting_power : ?chain:string -> ?block:string -> unit -> JSON.t t -(** RPC: [GET /chains/[chain]/blocks/[block]/context/dal/shards?level=[level]] *) +(** RPC: [GET /chains/[chain]/blocks/[block]/context/dal/shards] + + [chain] defaults to ["main"]. + [block] defaults to ["head"]. *) val get_chain_block_context_dal_shards : - ?chain:string -> ?block:string -> ?level:int -> unit -> JSON.t t + ?chain:string -> + ?block:string -> + ?level:int -> + ?delegates:string list -> + unit -> + JSON.t t (** RPC: [GET /monitor/applied_blocks] *) val get_monitor_applied_blocks : JSON.t t diff --git a/tezt/lib_tezos/dal_common.ml b/tezt/lib_tezos/dal_common.ml index 76817967accc1dee3ec8376482cb378aeb380686..d247a855768a07028a259499beb9765b31c598e1 100644 --- a/tezt/lib_tezos/dal_common.ml +++ b/tezt/lib_tezos/dal_common.ml @@ -83,7 +83,7 @@ module Parameters = struct end module Committee = struct - type member = {attester : string; first_shard_index : int; power : int} + type member = {attester : string; indexes : int list} type t = member list @@ -91,21 +91,22 @@ module Committee = struct let open Check in list @@ convert - (fun {attester; first_shard_index; power} -> - (attester, first_shard_index, power)) - (tuple3 string int int) + (fun {attester; indexes} -> (attester, indexes)) + (tuple2 string (list int)) - let at_level node ~level = + let at_level node ?level ?delegates () = let* json = - Node.RPC.call node @@ RPC.get_chain_block_context_dal_shards ~level () + Node.RPC.call node + @@ RPC.get_chain_block_context_dal_shards ?level ?delegates () in return @@ List.map (fun json -> - let pkh = JSON.(json |=> 0 |> as_string) in - let first_shard_index = JSON.(json |=> 1 |=> 0 |> as_int) in - let power = JSON.(json |=> 1 |=> 1 |> as_int) in - {attester = pkh; first_shard_index; power}) + let attester = JSON.(json |-> "delegate" |> as_string) in + let indexes = + JSON.(json |-> "indexes" |> as_list |> List.map as_int) + in + {attester; indexes}) (JSON.as_list json) end diff --git a/tezt/lib_tezos/dal_common.mli b/tezt/lib_tezos/dal_common.mli index ba19b43c6eca6cb44bdd7b38b8626f44924caa5a..5df0dd0b98049db8827e38d093d70130ef6fd5f0 100644 --- a/tezt/lib_tezos/dal_common.mli +++ b/tezt/lib_tezos/dal_common.mli @@ -264,13 +264,14 @@ module Commitment : sig end module Committee : sig - type member = {attester : string; first_shard_index : int; power : int} + type member = {attester : string; indexes : int list} type t = member list val typ : t Check.typ - val at_level : Node.t -> level:int -> t Lwt.t + val at_level : + Node.t -> ?level:int -> ?delegates:string list -> unit -> t Lwt.t end module Check : sig diff --git a/tezt/lib_tezos/operation_core.ml b/tezt/lib_tezos/operation_core.ml index 4407dd160edd7357eb620dfc75b0e1f398699fca..147cd49a195ebe98701cb4fc280b8dc8474c2226 100644 --- a/tezt/lib_tezos/operation_core.ml +++ b/tezt/lib_tezos/operation_core.ml @@ -830,3 +830,7 @@ let inject_error_check_recommended_fee ~loc ~rex ~expected_fee op client = int ~error_msg:("The recommended fee is %L but expected %R at " ^ loc)) ; unit + +let dal_data_availibility_attester_not_in_committee = + rex + {|The attester (tz[\w\d]+), with slot ([\d]+), is not part of the DAL committee for the level ([\d]+)\.|} diff --git a/tezt/lib_tezos/operation_core.mli b/tezt/lib_tezos/operation_core.mli index 270f8833c89bda2cb0f51ef359427f63bbc2ec19..28e140fd41c4ebf99cb530277a86ab52cc58c78e 100644 --- a/tezt/lib_tezos/operation_core.mli +++ b/tezt/lib_tezos/operation_core.mli @@ -675,6 +675,13 @@ val rejected_by_full_mempool_with_needed_fee : rex Captures [hash]. *) val rejected_by_full_mempool_no_possible_fee : rex +(** Matches the message produced by + [Dal_data_availibility_attester_not_in_committee {attester; level; slot}] + from [src/proto_alpha/lib_protocol/dal_errors_repr]. + + Captures [attester], [level], and [slot]. *) +val dal_data_availibility_attester_not_in_committee : rex + (** Calls {!inject_and_capture2_stderr} and checks that the second captured group is [expected_fee]. diff --git a/tezt/tests/dal.ml b/tezt/tests/dal.ml index dd89750ab5f1398b17ce470053a570c8575ba9a7..4f5e021fb0866fd76febf6c95ac51cf53107ab4f 100644 --- a/tezt/tests/dal.ml +++ b/tezt/tests/dal.ml @@ -618,10 +618,10 @@ let test_one_committee_per_level _protocol _parameters _cryptobox node _client that is indeed the case. *) assert (current_level.cycle_position = 0) ; let* current_committee = - Dal.Committee.at_level node ~level:current_level.level + Dal.Committee.at_level node ~level:current_level.level () in let* next_committee = - Dal.Committee.at_level node ~level:(current_level.level + 1) + Dal.Committee.at_level node ~level:(current_level.level + 1) () in Check.((current_committee <> next_committee) Dal.Committee.typ) ~error_msg:"Unexpected equal DAL committees at subsequent levels: %L and %R" ; @@ -1046,24 +1046,16 @@ let test_slots_attestation_operation_dal_committee_membership_check protocol let* () = bake_for ~count:(num_cycles * blocks_per_cycle) client in (* We iterate until we find a level for which the new account has no assigned shard. Recall that the probability to not be assigned a shard is around - 3/4, we so a level is found quickly. *) + 3/4, so a level is found quickly. *) let rec iter () = let* level = Client.level client in - let* json = - Node.RPC.(call node @@ get_chain_block_context_dal_shards ~level ()) - in - let committee = - JSON.as_list json - |> List.map (fun tuple -> - let pair = JSON.as_list tuple in - match pair with - | [pkh; _] -> JSON.as_string pkh - | _ -> - Test.fail - "could not parse result of \ - [get_chain_block_context_dal_shards] RPC") - in - if List.mem new_account.public_key_hash committee then ( + let* committee = Dal.Committee.at_level node ~level () in + if + List.exists + (fun member -> + String.equal member.Dal.Committee.attester new_account.public_key_hash) + committee + then ( Log.info "Bake another block to change the DAL committee" ; let* () = bake_for client in iter ()) @@ -1087,7 +1079,13 @@ let test_slots_attestation_operation_dal_committee_membership_check protocol ~error_msg: "The new account is not a validator, the test needs to be adapted") ; let* (`OpHash _oph) = - inject_dal_attestation ~nb_slots ~level ~signer:new_account [] client + inject_dal_attestation + ~error:Operation.dal_data_availibility_attester_not_in_committee + ~nb_slots + ~level + ~signer:new_account + [] + client in (* Bake with all the bootstrap accounts, but not with the new account. *) let* () = @@ -2302,7 +2300,7 @@ let test_dal_node_get_assigned_shard_indices _protocol _parameters _cryptobox let* {level; _} = Node.RPC.(call node @@ get_chain_block_helper_current_level ()) in - let* committee_from_l1 = Dal.Committee.at_level node ~level in + let* committee_from_l1 = Dal.Committee.at_level node ~level () in let* shards_from_dal = Dal_RPC.(call dal_node @@ get_assigned_shard_indices ~level ~pkh) in @@ -2313,9 +2311,7 @@ let test_dal_node_get_assigned_shard_indices _protocol _parameters _cryptobox with | None -> Test.fail ~__LOC__ "pkh %S not found in committee from L1." pkh | Some member -> - let shards_from_l1 = - List.init member.power (fun i -> member.first_shard_index + i) - in + let shards_from_l1 = member.indexes in Check.( (shards_from_dal = shards_from_l1) (list int) @@ -2605,6 +2601,8 @@ let test_attester_with_bake_for _protocol parameters cryptobox node client let last_checked_level = intermediary_level + unattested_levels - 1 in let last_level = last_checked_level + lag + 1 in + Log.info "attestation_lag = %d" lag ; + (* Publish and bake with client *) let publish source ~index message = let* _op_hash = @@ -2624,6 +2622,7 @@ let test_attester_with_bake_for _protocol parameters cryptobox node client store_slot ~with_proof:false dal_node @@ make_slot ~slot_size slot_content) in + Log.info "Slot with %d index (normally) published at level %d" index level ; unit in let publish_and_bake ~from_level ~to_level delegates = @@ -2988,16 +2987,6 @@ let e2e_tests = num_extra_nodes = 2; } in - let test2 = - { - constants = Protocol.Constants_test; - attestation_lag = 3; - block_delay = 4; - number_of_dal_slots = 5; - beforehand_slot_injection = 5; - num_extra_nodes = 2; - } - in let mainnet1 = { constants = Protocol.Constants_mainnet; @@ -3018,7 +3007,7 @@ let e2e_tests = num_extra_nodes = 0; } in - [test1; test2; mainnet1; mainnet2] + [test1; mainnet1; mainnet2] (* This function allows to register new (end-to-end) tests using [scenario_with_all_nodes] helper. For that, it instantiate function @@ -3196,10 +3185,11 @@ let event_with_message_to_string = function {!check_events_with_topic}, except that what varies here is the shard index instead of slot index. Moreover, shards do not necessiraly start from 0 or end at number_of_shards - 1. *) -let check_events_with_message ~event_with_message dal_node ~from_shard ~to_shard - ~expected_commitment ~expected_level ~expected_pkh ~expected_slot = - let remaining = ref (to_shard - from_shard + 1) in - let seen = Array.make !remaining false in +let check_events_with_message ~event_with_message dal_node ~number_of_shards + ~shard_indexes ~expected_commitment ~expected_level ~expected_pkh + ~expected_slot = + let remaining = ref (List.length shard_indexes) in + let seen = Array.make number_of_shards false in let get_shard_index_opt event = let topic_slot_index = JSON.(event |-> "topic" |-> "slot_index" |> as_int) @@ -3228,21 +3218,23 @@ let check_events_with_message ~event_with_message dal_node ~from_shard ~to_shard in Some shard_index in + let all_seen () = + seen |> Array.to_seqi + |> Seq.for_all (fun (i, b) -> if List.mem i shard_indexes then b else true) + in wait_for_gossipsub_worker_event dal_node ~name:(event_with_message_to_string event_with_message) (fun event -> let*?? shard_index = get_shard_index_opt event in - let index = shard_index - from_shard in Check.( - (seen.(index) = false) + (seen.(shard_index) = false) bool ~error_msg: (sf "Shard_index %d already seen. Invariant broken" shard_index)) ; - seen.(index) <- true ; + seen.(shard_index) <- true ; let () = remaining := !remaining - 1 in - if !remaining = 0 && Array.for_all (fun b -> b) seen then Some () - else None) + if !remaining = 0 && all_seen () then Some () else None) type event_with_message_id = IHave of {pkh : string; slot_index : int} | IWant @@ -3253,11 +3245,11 @@ let event_with_message_id_to_string = function (** This function monitors the Gossipsub worker events whose name is given by [event_with_message_id]. It's somehow similar to function {!check_events_with_message}, but for IHave and IWant messages' events. *) -let check_events_with_message_id ~event_with_message_id dal_node ~from_shard - ~to_shard ~expected_commitment ~expected_level ~expected_pkh ~expected_slot - ~expected_peer = - let remaining = ref (to_shard - from_shard + 1) in - let seen = Array.make !remaining false in +let check_events_with_message_id ~event_with_message_id dal_node + ~number_of_shards ~shard_indexes ~expected_commitment ~expected_level + ~expected_pkh ~expected_slot ~expected_peer = + let remaining = ref (List.length shard_indexes) in + let seen = Array.make number_of_shards false in let get_shard_indices_of_messages event = let*?? () = check_expected expected_peer JSON.(event |-> "peer" |> as_string) @@ -3287,6 +3279,10 @@ let check_events_with_message_id ~event_with_message_id dal_node ~from_shard Some shard_index) message_ids in + let all_seen () = + seen |> Array.to_seqi + |> Seq.for_all (fun (i, b) -> if List.mem i shard_indexes then b else true) + in wait_for_gossipsub_worker_event ~name:(event_with_message_id_to_string event_with_message_id) dal_node @@ -3297,27 +3293,26 @@ let check_events_with_message_id ~event_with_message_id dal_node ~from_shard match shard_index_opt with | None -> () | Some shard_index -> - let index = shard_index - from_shard in Check.( - (seen.(index) = false) + (seen.(shard_index) = false) bool ~error_msg: (sf "Shard_index %d already seen. Invariant broken" shard_index)) ; - seen.(index) <- true ; + seen.(shard_index) <- true ; decr remaining) shard_indices ; - if !remaining = 0 && Array.for_all (fun b -> b) seen then Some () - else None) + if !remaining = 0 && all_seen () then Some () else None) (** This function is quite similar to those above, except that it checks that a range of messages (shards) on a tracked topic have been notified by GS to the DAL node. This is typically needed to then be able to attest slots. *) -let check_message_notified_to_app_event dal_node ~from_shard ~to_shard - ~expected_commitment ~expected_level ~expected_pkh ~expected_slot = - let remaining = ref (to_shard - from_shard + 1) in - let seen = Array.make !remaining false in +let check_message_notified_to_app_event dal_node ~number_of_shards + ~shard_indexes ~expected_commitment ~expected_level ~expected_pkh + ~expected_slot = + let remaining = ref (List.length shard_indexes) in + let seen = Array.make number_of_shards false in let get_shard_index_opt event = let level = JSON.(event |-> "level" |> as_int) in let slot_index = JSON.(event |-> "slot_index" |> as_int) in @@ -3330,21 +3325,23 @@ let check_message_notified_to_app_event dal_node ~from_shard ~to_shard let*?? () = check_expected expected_commitment commitment in Some shard_index in + let all_seen () = + seen |> Array.to_seqi + |> Seq.for_all (fun (i, b) -> if List.mem i shard_indexes then b else true) + in Dal_node.wait_for dal_node "gossipsub_transport_event-message_notified_to_app.v0" (fun event -> let*?? shard_index = get_shard_index_opt event in - let index = shard_index - from_shard in Check.( - (seen.(index) = false) + (seen.(shard_index) = false) bool ~error_msg: (sf "Shard_index %d already seen. Invariant broken" shard_index)) ; - seen.(index) <- true ; + seen.(shard_index) <- true ; let () = remaining := !remaining - 1 in - if !remaining = 0 && Array.for_all (fun b -> b) seen then Some () - else None) + if !remaining = 0 && all_seen () then Some () else None) (** Connect [dal_node1] and [dal_node2] using the bootstrap peer mechanism. [dal_node2] will use [dal_node1] as a bootstrap peer. @@ -3414,15 +3411,15 @@ let nodes_join_the_same_topics dal_node1 dal_node2 ~num_slots ~pkh1 = one at the attesattion level corresponding to [publish_level]. *) let waiters_publish_shards l1_committee dal_node commitment ~publish_level - ~slot_index = + ~slot_index ~number_of_shards = let open Dal.Committee in List.map - (fun {attester; first_shard_index; power} -> + (fun {attester; indexes} -> check_events_with_message ~event_with_message:Publish_message dal_node - ~from_shard:first_shard_index - ~to_shard:(first_shard_index + power - 1) + ~number_of_shards + ~shard_indexes:indexes ~expected_commitment:commitment ~expected_level:publish_level ~expected_pkh:attester @@ -3436,15 +3433,15 @@ let waiters_publish_shards l1_committee dal_node commitment ~publish_level The [l1_committee] used to determine the topic of published messages is the one at the attesattion level corresponding to [publish_level]. *) let waiter_receive_shards l1_committee dal_node commitment ~publish_level - ~slot_index ~pkh ~from_peer = + ~slot_index ~pkh ~from_peer ~number_of_shards = let open Dal.Committee in match List.find (fun {attester; _} -> attester = pkh) l1_committee with - | {attester; first_shard_index; power} -> + | {attester; indexes} -> check_events_with_message ~event_with_message:(Message_with_header from_peer) dal_node - ~from_shard:first_shard_index - ~to_shard:(first_shard_index + power - 1) + ~number_of_shards + ~shard_indexes:indexes ~expected_commitment:commitment ~expected_level:publish_level ~expected_pkh:attester @@ -3459,14 +3456,14 @@ let waiter_receive_shards l1_committee dal_node commitment ~publish_level The [l1_committee] used to determine the topic of published messages is the one at the attesattion level corresponding to [publish_level]. *) let waiter_successful_shards_app_notification l1_committee dal_node commitment - ~publish_level ~slot_index ~pkh = + ~publish_level ~slot_index ~pkh ~number_of_shards = let open Dal.Committee in match List.find (fun {attester; _} -> attester = pkh) l1_committee with - | {attester; first_shard_index; power} -> + | {attester; indexes} -> check_message_notified_to_app_event dal_node - ~from_shard:first_shard_index - ~to_shard:(first_shard_index + power - 1) + ~number_of_shards + ~shard_indexes:indexes ~expected_commitment:commitment ~expected_level:publish_level ~expected_pkh:attester @@ -3523,6 +3520,7 @@ let generic_gs_messages_exchange protocol parameters _cryptobox node client let* () = connect_nodes_via_p2p dal_node1 dal_node2 in let num_slots = parameters.Dal.Parameters.number_of_slots in + let number_of_shards = parameters.Dal.Parameters.cryptobox.number_of_shards in let account1 = Constant.bootstrap1 in let pkh1 = account1.public_key_hash in (* The two nodes join the same topics *) @@ -3552,7 +3550,7 @@ let generic_gs_messages_exchange protocol parameters _cryptobox node client let* publish_level = next_level node in let attested_level = publish_level + parameters.attestation_lag in let attestation_level = attested_level - 1 in - let* committee = Dal.Committee.at_level node ~level:attestation_level in + let* committee = Dal.Committee.at_level node ~level:attestation_level () in let waiter_publish_list = waiters_publish_shards @@ -3561,6 +3559,7 @@ let generic_gs_messages_exchange protocol parameters _cryptobox node client slot_commitment ~publish_level ~slot_index + ~number_of_shards in let waiter_receive_shards = waiter_receive_shards @@ -3572,6 +3571,7 @@ let generic_gs_messages_exchange protocol parameters _cryptobox node client ~pkh:pkh1 ~from_peer: JSON.(Dal_node.read_identity dal_node1 |-> "peer_id" |> as_string) + ~number_of_shards in let waiter_app_notifs = if expect_app_notification then @@ -3582,6 +3582,7 @@ let generic_gs_messages_exchange protocol parameters _cryptobox node client ~publish_level ~slot_index ~pkh:pkh1 + ~number_of_shards else unit in @@ -3670,6 +3671,7 @@ let _test_gs_prune_ihave_and_iwant protocol parameters _cryptobox node client repeat_i (n - 1) f in let crypto_params = parameters.Dal.Parameters.cryptobox in + let number_of_shards = crypto_params.number_of_shards in let slot_size = crypto_params.slot_size in let slot_content = generate_dummy_slot slot_size in @@ -3748,23 +3750,22 @@ let _test_gs_prune_ihave_and_iwant protocol parameters _cryptobox node client let* publish_level = next_level node in let attested_level = publish_level + parameters.attestation_lag in let attestation_level = attested_level - 1 in - let* committee = Dal.Committee.at_level node ~level:attestation_level in + let* committee = Dal.Committee.at_level node ~level:attestation_level () in - let Dal.Committee.{attester; first_shard_index; power} = + let Dal.Committee.{attester; indexes = shard_indexes} = match List.find (fun Dal.Committee.{attester; _} -> attester = pkh1) committee with - | {attester; first_shard_index; power} -> - {attester; first_shard_index; power} | exception Not_found -> Test.fail "Should not happen as %s is part of the committee" pkh1 + | v -> v in let iwant_events_waiter = check_events_with_message_id ~event_with_message_id:IWant dal_node1 - ~from_shard:first_shard_index - ~to_shard:(first_shard_index + power - 1) + ~number_of_shards + ~shard_indexes ~expected_commitment:commitment ~expected_level:publish_level ~expected_pkh:attester @@ -3775,8 +3776,8 @@ let _test_gs_prune_ihave_and_iwant protocol parameters _cryptobox node client check_events_with_message_id ~event_with_message_id:(IHave {pkh = pkh1; slot_index = 0}) dal_node2 - ~from_shard:first_shard_index - ~to_shard:(first_shard_index + power - 1) + ~number_of_shards + ~shard_indexes ~expected_commitment:commitment ~expected_level:publish_level ~expected_pkh:attester diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out index b1531bb1e30c120ffea509197a22a019779ab490..23fd8a4909f515c7c93c08eed7a93b0f6509445b 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- misc_protocol.out @@ -39,8 +39,8 @@ "dal_parametric": { "feature_enable": true, "incentives_enable": false, "number_of_slots": 16, "attestation_lag": 8, - "attestation_threshold": 66, "redundancy_factor": 16, - "page_size": 4096, "slot_size": 65536, "number_of_shards": 2048 }, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, "smart_rollup_arith_pvm_enable": false, "smart_rollup_origination_size": 6314, "smart_rollup_challenge_window_in_blocks": 120960, diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out index fd631fadbdea5ffdbeabb326e578814aa399874f..18fb176fa807c0dd212ef5ee792e3a229877e101 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- misc_protocol.out @@ -39,8 +39,8 @@ "dal_parametric": { "feature_enable": true, "incentives_enable": false, "number_of_slots": 16, "attestation_lag": 8, - "attestation_threshold": 66, "redundancy_factor": 16, - "page_size": 4096, "slot_size": 65536, "number_of_shards": 2048 }, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, "smart_rollup_arith_pvm_enable": false, "smart_rollup_origination_size": 6314, "smart_rollup_challenge_window_in_blocks": 120960, diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out index 55b3af2b38d98af05bb545fcdb58a27651cb53d1..e32252a663feab4e1d34363954dfed92052506b7 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- misc_protocol.out @@ -39,8 +39,8 @@ "dal_parametric": { "feature_enable": true, "incentives_enable": false, "number_of_slots": 16, "attestation_lag": 8, - "attestation_threshold": 66, "redundancy_factor": 16, - "page_size": 4096, "slot_size": 65536, "number_of_shards": 2048 }, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, "smart_rollup_arith_pvm_enable": false, "smart_rollup_origination_size": 6314, "smart_rollup_challenge_window_in_blocks": 120960, diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out index 2acfc59c2cbb0d31d9a1bf6743284bfe390cbea3..fa4874fddcc188b0465d07fa6067a145b8bf5785 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- misc_protocol.out @@ -39,8 +39,8 @@ "dal_parametric": { "feature_enable": true, "incentives_enable": false, "number_of_slots": 16, "attestation_lag": 8, - "attestation_threshold": 66, "redundancy_factor": 16, - "page_size": 4096, "slot_size": 65536, "number_of_shards": 2048 }, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, "smart_rollup_arith_pvm_enable": false, "smart_rollup_origination_size": 6314, "smart_rollup_challenge_window_in_blocks": 120960, diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out index 2acfc59c2cbb0d31d9a1bf6743284bfe390cbea3..fa4874fddcc188b0465d07fa6067a145b8bf5785 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- misc_protocol.out @@ -39,8 +39,8 @@ "dal_parametric": { "feature_enable": true, "incentives_enable": false, "number_of_slots": 16, "attestation_lag": 8, - "attestation_threshold": 66, "redundancy_factor": 16, - "page_size": 4096, "slot_size": 65536, "number_of_shards": 2048 }, + "attestation_threshold": 66, "redundancy_factor": 8, "page_size": 3967, + "slot_size": 126944, "number_of_shards": 256 }, "smart_rollup_arith_pvm_enable": false, "smart_rollup_origination_size": 6314, "smart_rollup_challenge_window_in_blocks": 120960, diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (mainnet_lag-3_time-10_preinject-1_sl.out b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (mainnet_lag-3_time-10_preinject-1_sl.out index 49c59a0490de3128b74a0d62b09151fe76f24b96..3315b709735eec2f90afbb8d648e30c017d4866a 100644 --- a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (mainnet_lag-3_time-10_preinject-1_sl.out +++ b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (mainnet_lag-3_time-10_preinject-1_sl.out @@ -34,9 +34,9 @@ This sequence of operations was run: Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" -./octez-client --wait none send smart rollup message '[" dal:256:3:256:5 "]' from bootstrap2 +./octez-client --wait none send smart rollup message '[" dal:32:3:32:5 "]' from bootstrap2 Node is bootstrapped. -Estimated gas: 170.826 units (will add 100 for safety) +Estimated gas: 170.750 units (will add 100 for safety) Estimated storage: no bytes added Operation successfully injected in the node. Operation hash is '[OPERATION_HASH]' @@ -47,16 +47,16 @@ and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: From: [PUBLIC_KEY_HASH] - Fee to the baker: ꜩ0.000277 + Fee to the baker: ꜩ0.000275 Expected counter: 1 Gas limit: 271 Storage limit: 0 bytes Balance updates: - [PUBLIC_KEY_HASH] ... -ꜩ0.000277 - payload fees(the block proposer) ....... +ꜩ0.000277 + [PUBLIC_KEY_HASH] ... -ꜩ0.000275 + payload fees(the block proposer) ....... +ꜩ0.000275 Smart rollup messages submission: This smart rollup messages submission was successfully applied - Consumed gas: 170.760 + Consumed gas: 170.684 ./octez-client --wait none send smart rollup message '[" value"]' from bootstrap2 diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (mainnet_lag-3_time-5_preinject-10_sl.out b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (mainnet_lag-3_time-5_preinject-10_sl.out index e3abe8d06354264b741a6341971e749c52d7e991..2cc8320b31964dd187cf8143197620e6b03f22f9 100644 --- a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (mainnet_lag-3_time-5_preinject-10_sl.out +++ b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (mainnet_lag-3_time-5_preinject-10_sl.out @@ -34,9 +34,9 @@ This sequence of operations was run: Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" -./octez-client --wait none send smart rollup message '[" dal:256:3:256:5 "]' from bootstrap2 +./octez-client --wait none send smart rollup message '[" dal:32:3:32:5 "]' from bootstrap2 Node is bootstrapped. -Estimated gas: 170.826 units (will add 100 for safety) +Estimated gas: 170.750 units (will add 100 for safety) Estimated storage: no bytes added Operation successfully injected in the node. Operation hash is '[OPERATION_HASH]' @@ -47,16 +47,16 @@ and/or an external block explorer to make sure that it has been included. This sequence of operations was run: Manager signed operations: From: [PUBLIC_KEY_HASH] - Fee to the baker: ꜩ0.000277 + Fee to the baker: ꜩ0.000275 Expected counter: 1 Gas limit: 271 Storage limit: 0 bytes Balance updates: - [PUBLIC_KEY_HASH] ... -ꜩ0.000277 - payload fees(the block proposer) ....... +ꜩ0.000277 + [PUBLIC_KEY_HASH] ... -ꜩ0.000275 + payload fees(the block proposer) ....... +ꜩ0.000275 Smart rollup messages submission: This smart rollup messages submission was successfully applied - Consumed gas: 170.760 + Consumed gas: 170.684 ./octez-client --wait none send smart rollup message '["++++ value"]' from bootstrap2 diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out index d64fd51a1bf9c21c47d02c5e16d6b3667b7bb03c..b1c30c2808ffb61a4a971609e9a7f20d630a75a8 100644 --- a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out +++ b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (rollup_node_applies_dal_pages).out @@ -38,7 +38,7 @@ Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" { "level": 2, "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } -./octez-client --wait none send smart rollup message '["dal:16:8:16:0:2:4:6"]' from bootstrap2 +./octez-client --wait none send smart rollup message '["dal:16:8:32:0:2:4:6"]' from bootstrap2 Node is bootstrapped. Estimated gas: 170.903 units (will add 100 for safety) Estimated storage: no bytes added diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out index 740ae285403675f6e6d47b4f64bd0519197da403..b550bb53b458aa36c7520931ebc1e4dd72f79801 100644 --- a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out +++ b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (rollup_node_downloads_slots).out @@ -38,7 +38,7 @@ Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" { "level": 2, "commitment_hash": "[SC_ROLLUP_COMMITMENT_HASH]" } -./octez-client --wait none send smart rollup message '["dal:16:8:16:0:2:4:6"]' from bootstrap2 +./octez-client --wait none send smart rollup message '["dal:16:8:32:0:2:4:6"]' from bootstrap2 Node is bootstrapped. Estimated gas: 170.903 units (will add 100 for safety) Estimated storage: no bytes added diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (test_lag-3_time-12_preinject-1_slots.out b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (test_lag-3_time-12_preinject-1_slots.out index a73abd633dde7a5ade9a0da51a19f3c7fc2796e0..b66d0546d08dac756609853b242ff4f269fe55ba 100644 --- a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (test_lag-3_time-12_preinject-1_slots.out +++ b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (test_lag-3_time-12_preinject-1_slots.out @@ -34,7 +34,7 @@ This sequence of operations was run: Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" -./octez-client --wait none send smart rollup message '[" dal:16:3:16:5 "]' from bootstrap2 +./octez-client --wait none send smart rollup message '[" dal:16:3:32:5 "]' from bootstrap2 Node is bootstrapped. Estimated gas: 170.750 units (will add 100 for safety) Estimated storage: no bytes added diff --git a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (test_lag-3_time-4_preinject-5_slots-.out b/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (test_lag-3_time-4_preinject-5_slots-.out deleted file mode 100644 index 764b15a75e10fc2d725623e98047c5a8b8035902..0000000000000000000000000000000000000000 --- a/tezt/tests/expected/dal.ml/Alpha- Testing DAL rollup and node with L1 (test_lag-3_time-4_preinject-5_slots-.out +++ /dev/null @@ -1,97 +0,0 @@ - -./octez-client --wait none originate smart rollup rollup from '[PUBLIC_KEY_HASH]' of kind arith of type string with kernel --burn-cap 9999999 -Node is bootstrapped. -Estimated gas: 1930.030 units (will add 100 for safety) -Estimated storage: 6552 bytes added (will add 20 for safety) -Operation successfully injected in the node. -Operation hash is '[OPERATION_HASH]' -NOT waiting for the operation to be included. -Use command - octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] -and/or an external block explorer to make sure that it has been included. -This sequence of operations was run: - Manager signed operations: - From: [PUBLIC_KEY_HASH] - Fee to the baker: ꜩ0.000441 - Expected counter: 1 - Gas limit: 2031 - Storage limit: 6572 bytes - Balance updates: - [PUBLIC_KEY_HASH] ... -ꜩ0.000441 - payload fees(the block proposer) ....... +ꜩ0.000441 - Smart rollup origination: - Kind: arith - Parameter type: string - Kernel Blake2B hash: '0e5751c026e543b2e8ab2eb06099daa1d1e5df47778f7787faab45cdf12fe3a8' - This smart rollup origination was successfully applied - Consumed gas: 1929.997 - Storage size: 6552 bytes - Address: [SMART_ROLLUP_HASH] - Genesis commitment hash: [SC_ROLLUP_COMMITMENT_HASH] - Balance updates: - [PUBLIC_KEY_HASH] ... -ꜩ1.638 - storage fees ........................... +ꜩ1.638 - -Smart rollup [SMART_ROLLUP_HASH] memorized as "rollup" - -./octez-client --wait none send smart rollup message '[" dal:16:3:16:5 "]' from bootstrap2 -Node is bootstrapped. -Estimated gas: 170.750 units (will add 100 for safety) -Estimated storage: no bytes added -Operation successfully injected in the node. -Operation hash is '[OPERATION_HASH]' -NOT waiting for the operation to be included. -Use command - octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] -and/or an external block explorer to make sure that it has been included. -This sequence of operations was run: - Manager signed operations: - From: [PUBLIC_KEY_HASH] - Fee to the baker: ꜩ0.000275 - Expected counter: 1 - Gas limit: 271 - Storage limit: 0 bytes - Balance updates: - [PUBLIC_KEY_HASH] ... -ꜩ0.000275 - payload fees(the block proposer) ....... +ꜩ0.000275 - Smart rollup messages submission: - This smart rollup messages submission was successfully applied - Consumed gas: 170.684 - - -./octez-client --wait none send smart rollup message '["++++ value"]' from bootstrap2 -Node is bootstrapped. -Estimated gas: 170.559 units (will add 100 for safety) -Estimated storage: no bytes added -Operation successfully injected in the node. -Operation hash is '[OPERATION_HASH]' -NOT waiting for the operation to be included. -Use command - octez-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] -and/or an external block explorer to make sure that it has been included. -This sequence of operations was run: - Manager signed operations: - From: [PUBLIC_KEY_HASH] - Fee to the baker: ꜩ0.00027 - Expected counter: 7 - Gas limit: 271 - Storage limit: 0 bytes - Balance updates: - [PUBLIC_KEY_HASH] ... -ꜩ0.00027 - payload fees(the block proposer) ....... +ꜩ0.00027 - Smart rollup messages submission: - This smart rollup messages submission was successfully applied - Consumed gas: 170.492 - -GET http://[HOST]:[PORT]/global/block/head/state?key=vars/value -200 OK -"00000037" - -GET http://[HOST]:[PORT]/global/block/head/state?key=vars/value -200 OK -"00000037" - -GET http://[HOST]:[PORT]/global/block/head/state?key=vars/value -200 OK -"00000037" -