diff --git a/src/proto_023_PtSeouLo/lib_delegate/baking_state.ml b/src/proto_023_PtSeouLo/lib_delegate/baking_state.ml index 3e69420fe4c66ce914aa580b807dbad5f48ee684..bee661d3fe7225cce293f0319423eec060f87d6f 100644 --- a/src/proto_023_PtSeouLo/lib_delegate/baking_state.ml +++ b/src/proto_023_PtSeouLo/lib_delegate/baking_state.ml @@ -36,7 +36,7 @@ type prequorum = { level : int32; round : Round.t; block_payload_hash : Block_payload_hash.t; - preattestations : Kind.preattestation operation list; + preattestations : packed_operation list; } type block_info = { @@ -46,7 +46,7 @@ type block_info = { payload_round : Round.t; round : Round.t; prequorum : prequorum option; - quorum : Kind.attestation operation list; + quorum : packed_operation list; payload : Operation_pool.payload; grandparent : Block_hash.t; } @@ -59,15 +59,9 @@ let prequorum_encoding = let open Data_encoding in conv (fun {level; round; block_payload_hash; preattestations} -> - (level, round, block_payload_hash, List.map Operation.pack preattestations)) + (level, round, block_payload_hash, preattestations)) (fun (level, round, block_payload_hash, preattestations) -> - { - level; - round; - block_payload_hash; - preattestations = - List.filter_map Operation_pool.unpack_preattestation preattestations; - }) + {level; round; block_payload_hash; preattestations}) (obj4 (req "level" int32) (req "round" Round.encoding) @@ -94,7 +88,7 @@ let block_info_encoding = payload_round, round, prequorum, - List.map Operation.pack quorum, + quorum, payload, grandparent )) (fun ( hash, @@ -114,7 +108,7 @@ let block_info_encoding = payload_round; round; prequorum; - quorum = List.filter_map Operation_pool.unpack_attestation quorum; + quorum; payload; }) (obj9 diff --git a/src/proto_023_PtSeouLo/lib_delegate/baking_state.mli b/src/proto_023_PtSeouLo/lib_delegate/baking_state.mli index 7e4e6b3eace25dd9ded479fa4d1748474bb8ee58..5c236fbe16b46b55c92dd1e725ee743b1b5df9be 100644 --- a/src/proto_023_PtSeouLo/lib_delegate/baking_state.mli +++ b/src/proto_023_PtSeouLo/lib_delegate/baking_state.mli @@ -199,7 +199,7 @@ type prequorum = { level : int32; round : Round.t; block_payload_hash : Block_payload_hash.t; - preattestations : Kind.preattestation operation list; + preattestations : packed_operation list; } type block_info = { @@ -209,7 +209,7 @@ type block_info = { payload_round : Round.t; round : Round.t; prequorum : prequorum option; - quorum : Kind.attestation operation list; + quorum : packed_operation list; payload : Operation_pool.payload; grandparent : Block_hash.t; } diff --git a/src/proto_023_PtSeouLo/lib_delegate/block_forge.ml b/src/proto_023_PtSeouLo/lib_delegate/block_forge.ml index 1b2279012dd4818bc9013e42a300691586b82285..87395fd12a35ac2a3541400cb8c15ebd0c7a4f3f 100644 --- a/src/proto_023_PtSeouLo/lib_delegate/block_forge.ml +++ b/src/proto_023_PtSeouLo/lib_delegate/block_forge.ml @@ -496,8 +496,12 @@ let aggregate_attestations eligible_attestations = let partition_consensus_operations_on_proposal consensus_operations = let open Operation_pool in Prioritized_operation_set.fold - (fun operation (eligible_attestations, remaining_operations) -> - let {shell; protocol_data = Operation_data protocol_data; _} = + (fun operation + ( attestations_aggregate_opt, + eligible_attestations, + remaining_operations ) -> + let ({shell; protocol_data = Operation_data protocol_data; _} as + packed_operation) = Prioritized_operation.packed operation in match (protocol_data.contents, protocol_data.signature) with @@ -508,10 +512,27 @@ let partition_consensus_operations_on_proposal consensus_operations = let remaining_operations = Prioritized_operation_set.remove operation remaining_operations in - (attestation :: eligible_attestations, remaining_operations) - | _, _ -> (eligible_attestations, remaining_operations)) + ( attestations_aggregate_opt, + attestation :: eligible_attestations, + remaining_operations ) + | ( Single (Attestations_aggregate {consensus_content; committee}), + Some (Bls signature) ) -> + let attestations_aggregate_opt = + Some + (shell, consensus_content, committee, signature, packed_operation) + in + let remaining_operations = + Prioritized_operation_set.remove operation remaining_operations + in + ( attestations_aggregate_opt, + eligible_attestations, + remaining_operations ) + | _, _ -> + ( attestations_aggregate_opt, + eligible_attestations, + remaining_operations )) consensus_operations - ([], consensus_operations) + (None, [], consensus_operations) (* [partition_consensus_operations_on_reproposal consensus_operations] partitions [consensus_operations] as follows : @@ -616,61 +637,42 @@ let filter_best_attestations_per_slot attestations = in SlotMap.fold (fun _slot attestation acc -> attestation :: acc) slot_map [] -(* [aggregate_attestations_on_proposal attestations] replaces all eligible - attestations from [attestations] by a single Attestations_aggregate. - - All attestations are assumed to target the same branch, level, round and - block_payload_hash. *) -let aggregate_attestations_on_proposal attestations = - let open Result_syntax in - let eligible_attestations, remaining_attestations = - partition_consensus_operations_on_proposal attestations - in - let* aggregate_opt = - eligible_attestations |> filter_best_attestations_per_slot - |> aggregate_attestations - in - match aggregate_opt with - | Some aggregate -> - let open Operation_pool in - return - @@ Prioritized_operation_set.add - (Prioritized_operation.extern ~priority:1 aggregate) - remaining_attestations - | None -> return remaining_attestations - module SlotSet : Set.S with type elt = Slot.t = Set.Make (Slot) -let aggregate_preattestations_on_reproposal aggregate_opt - eligible_preattestations = +let aggregate_attestations aggregate_opt eligible_attestations = let open Result_syntax in - match (aggregate_opt, eligible_preattestations) with + let eligible_attestations = + filter_best_attestations_per_slot eligible_attestations + in + match (aggregate_opt, eligible_attestations) with | None, [] -> return_none | None, _ :: _ -> (* The proposal did not contain an aggregate. Since additional eligible - preattestations are available, we must aggregate them and include the + attestations are available, we must aggregate them and include the result in the reproposal. *) - aggregate_preattestations eligible_preattestations + aggregate_attestations eligible_attestations | Some (_, _, _, _, operation), [] -> return_some operation | Some (shell, consensus_content, committee, signature, _), _ :: _ -> ( (* The proposal already contains an aggregate. We must incorporate additional attestations *) let aggregated_slots = (* Build the set of aggregated slots for a logarithmic presence lookup *) - SlotSet.of_list committee + SlotSet.of_list (Operation.committee_slots committee) in (* Gather slots and signatures incorporating fresh attestations. *) let committee, signatures = List.fold_left (fun ((slots, signatures) as acc) - ({protocol_data; _} : Kind.preattestation operation) -> + ({protocol_data; _} : Kind.attestation operation) -> match (protocol_data.contents, protocol_data.signature) with - | Single (Preattestation consensus_content), Some (Bls signature) + | ( Single (Attestation {consensus_content; dal_content}), + Some (Bls signature) ) when not (SlotSet.mem consensus_content.slot aggregated_slots) -> - (consensus_content.slot :: slots, signature :: signatures) + ( (consensus_content.slot, dal_content) :: slots, + signature :: signatures ) | _ -> acc) (committee, [signature]) - eligible_preattestations + eligible_attestations in (* We disable the subgroup check for better performance, as operations come from the mempool where it has already been checked. *) @@ -679,49 +681,68 @@ let aggregate_preattestations_on_reproposal aggregate_opt with | Some signature -> let contents = - Single (Preattestations_aggregate {consensus_content; committee}) + Single (Attestations_aggregate {consensus_content; committee}) in let protocol_data = {contents; signature = Some (Bls signature)} in - let preattestations_aggregate = + let attestations_aggregate = {shell; protocol_data = Operation_data protocol_data} in - return_some preattestations_aggregate + return_some attestations_aggregate | None -> tzfail Baking_errors.Signature_aggregation_failure) -let aggregate_attestations_on_reproposal aggregate_opt eligible_attestations = +(* [aggregate_attestations_on_proposal attestations] replaces all eligible + attestations from [attestations] by a single Attestations_aggregate. + + All attestations are assumed to target the same branch, level, round and + block_payload_hash. *) +let aggregate_attestations_on_proposal attestations = let open Result_syntax in - let eligible_attestations = - filter_best_attestations_per_slot eligible_attestations + let attestations_aggregate_opt, eligible_attestations, remaining_attestations + = + partition_consensus_operations_on_proposal attestations in - match (aggregate_opt, eligible_attestations) with + let* aggregate_opt = + aggregate_attestations attestations_aggregate_opt eligible_attestations + in + match aggregate_opt with + | Some aggregate -> + let open Operation_pool in + return + @@ Prioritized_operation_set.add + (Prioritized_operation.extern ~priority:1 aggregate) + remaining_attestations + | None -> return remaining_attestations + +let aggregate_preattestations_on_reproposal aggregate_opt + eligible_preattestations = + let open Result_syntax in + match (aggregate_opt, eligible_preattestations) with | None, [] -> return_none | None, _ :: _ -> (* The proposal did not contain an aggregate. Since additional eligible - attestations are available, we must aggregate them and include the + preattestations are available, we must aggregate them and include the result in the reproposal. *) - aggregate_attestations eligible_attestations + aggregate_preattestations eligible_preattestations | Some (_, _, _, _, operation), [] -> return_some operation | Some (shell, consensus_content, committee, signature, _), _ :: _ -> ( (* The proposal already contains an aggregate. We must incorporate additional attestations *) let aggregated_slots = (* Build the set of aggregated slots for a logarithmic presence lookup *) - SlotSet.of_list (Operation.committee_slots committee) + SlotSet.of_list committee in (* Gather slots and signatures incorporating fresh attestations. *) let committee, signatures = List.fold_left (fun ((slots, signatures) as acc) - ({protocol_data; _} : Kind.attestation operation) -> + ({protocol_data; _} : Kind.preattestation operation) -> match (protocol_data.contents, protocol_data.signature) with - | ( Single (Attestation {consensus_content; dal_content}), - Some (Bls signature) ) + | Single (Preattestation consensus_content), Some (Bls signature) when not (SlotSet.mem consensus_content.slot aggregated_slots) -> - ( (consensus_content.slot, dal_content) :: slots, - signature :: signatures ) + (consensus_content.slot :: slots, signature :: signatures) | _ -> acc) (committee, [signature]) - eligible_attestations + eligible_preattestations in (* We disable the subgroup check for better performance, as operations come from the mempool where it has already been checked. *) @@ -730,13 +751,13 @@ let aggregate_attestations_on_reproposal aggregate_opt eligible_attestations = with | Some signature -> let contents = - Single (Attestations_aggregate {consensus_content; committee}) + Single (Preattestations_aggregate {consensus_content; committee}) in let protocol_data = {contents; signature = Some (Bls signature)} in - let attestations_aggregate = + let preattestations_aggregate = {shell; protocol_data = Operation_data protocol_data} in - return_some attestations_aggregate + return_some preattestations_aggregate | None -> tzfail Baking_errors.Signature_aggregation_failure) (* [aggregate_consensus_operations_on_reproposal consensus_operations] replaces @@ -756,9 +777,7 @@ let aggregate_consensus_operations_on_reproposal consensus_operations = partition_consensus_operations_on_reproposal consensus_operations in let* attestations_aggregate_opt = - aggregate_attestations_on_reproposal - attestations_aggregate_opt - eligible_attestations + aggregate_attestations attestations_aggregate_opt eligible_attestations in let* preattestations_aggregate_opt = aggregate_preattestations_on_reproposal diff --git a/src/proto_023_PtSeouLo/lib_delegate/node_rpc.ml b/src/proto_023_PtSeouLo/lib_delegate/node_rpc.ml index 57305a1c4099616acab78e46f37ea9b0e9ec6014..92d0e8a2d58e458044fde4975e6d8ec6ba49cf10 100644 --- a/src/proto_023_PtSeouLo/lib_delegate/node_rpc.ml +++ b/src/proto_023_PtSeouLo/lib_delegate/node_rpc.ml @@ -72,19 +72,39 @@ let preapply_block cctxt ~chain ~head ~timestamp ~protocol_data operations = operations ~protocol_data -let extract_prequorum preattestations = +let extract_prequorum (preattestations : packed_operation list) = match preattestations with - | h :: _ -> - let {protocol_data = {contents = Single (Preattestation content); _}; _} = - (h : Kind.preattestation Operation.t) - in - Some - { - level = Raw_level.to_int32 content.level; - round = content.round; - block_payload_hash = content.block_payload_hash; - preattestations; - } + | h :: _ -> ( + match h with + | { + protocol_data = + Operation_data {contents = Single (Preattestation content); _}; + _; + } -> + Some + { + level = Raw_level.to_int32 content.level; + round = content.round; + block_payload_hash = content.block_payload_hash; + preattestations; + } + | { + protocol_data = + Operation_data + { + contents = Single (Preattestations_aggregate {consensus_content; _}); + _; + }; + _; + } -> + Some + { + level = Raw_level.to_int32 consensus_content.level; + round = consensus_content.round; + block_payload_hash = consensus_content.block_payload_hash; + preattestations; + } + | _ -> None) | _ -> None let info_of_header_and_ops ~in_protocol ~grandparent block_hash block_header diff --git a/src/proto_023_PtSeouLo/lib_delegate/operation_pool.ml b/src/proto_023_PtSeouLo/lib_delegate/operation_pool.ml index 8fb6ccba01212ba1cc2ca1959ae68ed1a2afb91e..cf80556c6b0b91244c3326c527a49d4ce28c40d9 100644 --- a/src/proto_023_PtSeouLo/lib_delegate/operation_pool.ml +++ b/src/proto_023_PtSeouLo/lib_delegate/operation_pool.ml @@ -328,15 +328,25 @@ let extract_operations_of_list_list = function | [consensus; votes_payload; anonymous_payload; managers_payload] -> let preattestations, attestations = List.fold_left - (fun ( (preattestations : Kind.preattestation Operation.t list), - (attestations : Kind.attestation Operation.t list) ) + (fun ( (preattestations : packed_operation list), + (attestations : packed_operation list) ) packed_op -> let {shell; protocol_data = Operation_data data} = packed_op in match data with | {contents = Single (Preattestation _); _} -> - ({shell; protocol_data = data} :: preattestations, attestations) + ( Operation.pack {shell; protocol_data = data} :: preattestations, + attestations ) + | {contents = Single (Preattestations_aggregate _); _} -> + ( Operation.pack {shell; protocol_data = data} :: preattestations, + attestations ) | {contents = Single (Attestation _); _} -> - (preattestations, {shell; protocol_data = data} :: attestations) + ( preattestations, + Operation.pack {shell; protocol_data = data} :: attestations + ) + | {contents = Single (Attestations_aggregate _); _} -> + ( preattestations, + Operation.pack {shell; protocol_data = data} :: attestations + ) | _ -> (* unreachable *) (preattestations, attestations)) diff --git a/src/proto_023_PtSeouLo/lib_delegate/operation_pool.mli b/src/proto_023_PtSeouLo/lib_delegate/operation_pool.mli index 547cedf41bc6f332805c2ea4fd9e4e64229fb060..387c62b543069b1db3a68c5757bc9b7c7896754c 100644 --- a/src/proto_023_PtSeouLo/lib_delegate/operation_pool.mli +++ b/src/proto_023_PtSeouLo/lib_delegate/operation_pool.mli @@ -112,10 +112,7 @@ val ordered_of_list_list : packed_operation list list -> ordered_pool option (** [preattestation] <> None => (List.length preattestations > 0) *) val extract_operations_of_list_list : packed_operation list list -> - (Kind.preattestation operation list option - * Kind.attestation operation list - * payload) - option + (packed_operation list option * packed_operation list * payload) option module Prioritized_operation : sig type t diff --git a/src/proto_023_PtSeouLo/lib_delegate/state_transitions.ml b/src/proto_023_PtSeouLo/lib_delegate/state_transitions.ml index 7c99ec4c643123e6bc1e4b09e4f90d2991b56f42..6ba943e12e55e3fdb28dc2ecf14a3fabb3d2d193 100644 --- a/src/proto_023_PtSeouLo/lib_delegate/state_transitions.ml +++ b/src/proto_023_PtSeouLo/lib_delegate/state_transitions.ml @@ -197,32 +197,37 @@ let prepare_consensus_votes state proposal = let extract_pqc state (new_proposal : proposal) = match new_proposal.block.prequorum with | None -> None - | Some pqc -> - let add_voting_power acc (op : Kind.preattestation Operation.t) = - let open Protocol.Alpha_context.Operation in - let { - shell = _; - protocol_data = {contents = Single (Preattestation {slot; _}); _}; - _; - } = - op - in - match - Delegate_slots.voting_power state.level_state.delegate_slots ~slot - with - | None -> - (* cannot happen if the map is correctly populated *) - acc - | Some attesting_power -> acc + attesting_power - in + | Some prequorum -> let voting_power = - List.fold_left add_voting_power 0 pqc.preattestations + let voting_power_of_slot slot = + match + Delegate_slots.voting_power state.level_state.delegate_slots ~slot + with + | Some attesting_power -> attesting_power + | None -> 0 + in + List.fold_left + (fun voting_power op -> + let {protocol_data = Operation_data operation_data; _} = op in + match operation_data with + | {contents = Single (Preattestation {slot; _}); _} -> + voting_power_of_slot slot + voting_power + | {contents = Single (Preattestations_aggregate {committee; _}); _} + -> + List.fold_left + (fun aggregated_voting_power slot -> + voting_power_of_slot slot + aggregated_voting_power) + 0 + committee + | _ -> voting_power) + 0 + prequorum.preattestations in let consensus_threshold = state.global_state.constants.parametric.consensus_threshold_size in if Compare.Int.(voting_power >= consensus_threshold) then - Some (pqc.preattestations, pqc.round) + Some (prequorum.preattestations, prequorum.round) else None let may_update_attestable_payload_with_internal_pqc state @@ -572,9 +577,7 @@ let prepare_block_to_bake ~attestations ?last_proposal in (* 3. Add the additional given [attestations]. N.b. this is a set: there won't be duplicates *) - Operation_pool.add_operations - filtered_mempool - (List.map Operation.pack attestations) + Operation_pool.add_operations filtered_mempool attestations in let kind = Fresh operation_pool in let* () = Events.(emit preparing_fresh_block (delegate, round)) in @@ -652,8 +655,7 @@ let propose_block_action state delegate round ~last_proposal = List.fold_left (fun set op -> Operation_pool.Operation_set.add op set) mempool_consensus_operations - (List.map Operation.pack proposal.block.quorum - @ List.map Operation.pack prequorum.preattestations) + (proposal.block.quorum @ prequorum.preattestations) in let attestation_filter = { @@ -781,7 +783,7 @@ let time_to_prepare_next_level_block state at_round = triggered when we have a slot and an elected block *) assert false | Some elected_block, Some {delegate; _} -> - let attestations = elected_block.attestation_qc in + let attestations = List.map Operation.pack elected_block.attestation_qc in let new_level_state = {state.level_state with next_level_latest_forge_request = Some at_round} in @@ -931,8 +933,9 @@ let prequorum_reached_when_awaiting_preattestations state candidate level = latest_proposal.block.shell.level; round = latest_proposal.block.round; block_payload_hash = latest_proposal.block.payload_hash; - preattestations - (* preattestations may be nil when [consensus_threshold] is 0 *); + preattestations = + List.map Operation.pack preattestations + (* preattestations may be nil when [consensus_threshold] is 0 *); } in let new_attestable_payload = {proposal = latest_proposal; prequorum} in diff --git a/src/proto_023_PtSeouLo/lib_delegate/state_transitions.mli b/src/proto_023_PtSeouLo/lib_delegate/state_transitions.mli index 7ea10de844d0268ae45193ce32cc507c3216fe0f..7fad44c6eead789c5398b2307519f52632a19411 100644 --- a/src/proto_023_PtSeouLo/lib_delegate/state_transitions.mli +++ b/src/proto_023_PtSeouLo/lib_delegate/state_transitions.mli @@ -47,8 +47,7 @@ val may_update_proposal : val preattest : state -> proposal -> (state * action) Lwt.t -val extract_pqc : - state -> proposal -> (Kind.preattestation operation list * Round.t) option +val extract_pqc : state -> proposal -> (packed_operation list * Round.t) option val handle_proposal : is_proposal_applied:bool -> state -> proposal -> (state * action) Lwt.t