From eca6919eb990b51fe148f94c44abdf94c24feac9 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 9 Jan 2024 16:43:16 +0100 Subject: [PATCH 01/17] Alpha/DAL: merge consensus and DAL attestations into a new operation It includes having two tag-based encoding formats for attestations, based on whether they contain DAL attestations or not. Not all required changes are done in this commit, see also subsequent commits. --- .../lib_client/operation_result.ml | 2 +- .../lib_delegate/baking_actions.ml | 4 +- src/proto_alpha/lib_delegate/baking_lib.ml | 8 +- .../client_baking_denunciation.ml | 12 +- .../lib_delegate/operation_pool.ml | 7 +- .../lib_delegate/operation_worker.ml | 31 +++- .../test/mockup_simulator/mockup_simulator.ml | 2 +- src/proto_alpha/lib_plugin/RPC.ml | 4 +- src/proto_alpha/lib_plugin/mempool.ml | 2 +- .../lib_protocol/alpha_context.mli | 12 +- src/proto_alpha/lib_protocol/apply.ml | 5 +- src/proto_alpha/lib_protocol/apply_results.ml | 68 +++++++- .../lib_protocol/operation_repr.ml | 162 ++++++++++++++---- .../lib_protocol/operation_repr.mli | 12 +- .../lib_protocol/test/helpers/op.ml | 11 +- .../lib_protocol/test/helpers/op.mli | 4 +- .../test/helpers/operation_generator.ml | 2 +- .../integration/consensus/test_attestation.ml | 2 +- src/proto_alpha/lib_protocol/validate.ml | 26 ++- 19 files changed, 302 insertions(+), 74 deletions(-) diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 3286b70a9f3e..9c7f0ad278ba 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -1004,7 +1004,7 @@ let pp_contents_and_result : Consensus_key.pp {delegate; consensus_pkh = consensus_key} consensus_power - | ( Attestation {level; _}, + | ( Attestation {consensus_content = {level; _}; dal_content = _}, Attestation_result {balance_updates; delegate; consensus_key; consensus_power} ) -> Format.fprintf diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 3eae944cab14..9f4388dbf4bd 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -577,7 +577,9 @@ let sign_consensus_votes state operations kind = | `Attestation -> forge_and_sign_consensus_vote delegate - (Single (Attestation consensus_content)) + (Single + (Attestation + {consensus_content; dal_content = None (* TODO *)})) | `Preattestation -> forge_and_sign_consensus_vote delegate diff --git a/src/proto_alpha/lib_delegate/baking_lib.ml b/src/proto_alpha/lib_delegate/baking_lib.ml index cde77917b881..a04de01a2f89 100644 --- a/src/proto_alpha/lib_delegate/baking_lib.ml +++ b/src/proto_alpha/lib_delegate/baking_lib.ml @@ -208,7 +208,11 @@ let state_attesting_power = Operation_pool.filter_attestations (fun ({ - protocol_data = {contents = Single (Attestation consensus_content); _}; + protocol_data = + { + contents = Single (Attestation {consensus_content; dal_content = _}); + _; + }; _; } : Kind.attestation operation) @@ -500,7 +504,7 @@ let rec baking_minimal_timestamp ~count state (fun ({ protocol_data = - {contents = Single (Attestation consensus_content); _}; + {contents = Single (Attestation {consensus_content; _}); _}; _; } : Kind.attestation operation) diff --git a/src/proto_alpha/lib_delegate/client_baking_denunciation.ml b/src/proto_alpha/lib_delegate/client_baking_denunciation.ml index bd6157654fe6..7ffdd3e924c0 100644 --- a/src/proto_alpha/lib_delegate/client_baking_denunciation.ml +++ b/src/proto_alpha/lib_delegate/client_baking_denunciation.ml @@ -142,14 +142,14 @@ let get_payload_hash (type kind) (op_kind : kind consensus_operation_type) (op : kind Operation.t) = match (op_kind, op.protocol_data.contents) with | Preattestation, Single (Preattestation consensus_content) - | Attestation, Single (Attestation consensus_content) -> + | Attestation, Single (Attestation {consensus_content; _}) -> consensus_content.block_payload_hash let get_slot (type kind) (op_kind : kind consensus_operation_type) (op : kind Operation.t) = match (op_kind, op.protocol_data.contents) with | Preattestation, Single (Preattestation consensus_content) - | Attestation, Single (Attestation consensus_content) -> + | Attestation, Single (Attestation {consensus_content; _}) -> consensus_content.slot let double_consensus_op_evidence (type kind) : @@ -349,8 +349,12 @@ let process_operations (cctxt : #Protocol_client_context.full) state round slot | Operation_data - ({contents = Single (Attestation {round; slot; level; _}); _} as - protocol_data) -> + ({ + contents = + Single + (Attestation {consensus_content = {round; slot; level; _}; _}); + _; + } as protocol_data) -> let new_attestation : Kind.attestation Alpha_context.operation = {shell; protocol_data} in diff --git a/src/proto_alpha/lib_delegate/operation_pool.ml b/src/proto_alpha/lib_delegate/operation_pool.ml index 7d9ca75987de..91eafcf24502 100644 --- a/src/proto_alpha/lib_delegate/operation_pool.ml +++ b/src/proto_alpha/lib_delegate/operation_pool.ml @@ -242,7 +242,12 @@ let filter_with_relevant_consensus_ops ~(attestation_filter : consensus_filter) | ( Operation_data { contents = - Single (Attestation {level; round; block_payload_hash; _}); + Single + (Attestation + { + consensus_content = {level; round; block_payload_hash; _}; + dal_content = _; + }); _; }, _ ) -> diff --git a/src/proto_alpha/lib_delegate/operation_worker.ml b/src/proto_alpha/lib_delegate/operation_worker.ml index ec1bb0b87bd6..3a591333e6b3 100644 --- a/src/proto_alpha/lib_delegate/operation_worker.ml +++ b/src/proto_alpha/lib_delegate/operation_worker.ml @@ -181,9 +181,27 @@ module Attestation_set = Set.Make (struct type t = Kind.attestation operation let compare - ({protocol_data = {contents = Single (Attestation op1); _}; shell = _} : + ({ + protocol_data = + { + contents = + Single + (Attestation + {consensus_content = op1; dal_content = _ (* TODO *)}); + _; + }; + shell = _; + } : t) - ({protocol_data = {contents = Single (Attestation op2); _}; shell = _} : + ({ + protocol_data = + { + contents = + Single (Attestation {consensus_content = op2; dal_content = _}); + _; + }; + shell = _; + } : t) = compare_consensus_contents op1 op2 end) @@ -399,7 +417,7 @@ let update_monitoring ?(should_lock = true) state ops = let { shell = _; protocol_data = - {contents = Single (Attestation consensus_content); _}; + {contents = Single (Attestation {consensus_content; _}); _}; _; } = op @@ -525,7 +543,12 @@ let update_operations_pool state (head_level, head_round) = | { protocol_data = Operation_data - {contents = Single (Attestation {round; level; _}); _}; + { + contents = + Single + (Attestation {consensus_content = {round; level; _}; _}); + _; + }; _; } -> let round_i32 = Round.to_int32 round in diff --git a/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.ml b/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.ml index 1f8b6d0b015f..6f14bb589d44 100644 --- a/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.ml +++ b/src/proto_alpha/lib_delegate/test/mockup_simulator/mockup_simulator.ml @@ -1508,7 +1508,7 @@ let op_is_attestation ?level ?round (op_hash : Operation_hash.t) match d.contents with | Single op_contents -> ( match op_contents with - | Attestation consensus_content -> + | Attestation {consensus_content; _} -> let right_level = match level with | None -> true diff --git a/src/proto_alpha/lib_plugin/RPC.ml b/src/proto_alpha/lib_plugin/RPC.ml index f86965d50502..dfedda356909 100644 --- a/src/proto_alpha/lib_plugin/RPC.ml +++ b/src/proto_alpha/lib_plugin/RPC.ml @@ -3358,8 +3358,8 @@ module Forge = struct () ({branch}, Contents_list (Single operation)) - let attestation ctxt b ~branch ~consensus_content () = - operation ctxt b ~branch (Attestation consensus_content) + let attestation ctxt b ~branch ~consensus_content ?dal_content () = + operation ctxt b ~branch (Attestation {consensus_content; dal_content}) let proposals ctxt b ~branch ~source ~period ~proposals () = operation ctxt b ~branch (Proposals {source; period; proposals}) diff --git a/src/proto_alpha/lib_plugin/mempool.ml b/src/proto_alpha/lib_plugin/mempool.ml index 891325ce7b01..6f5a0fc72074 100644 --- a/src/proto_alpha/lib_plugin/mempool.ml +++ b/src/proto_alpha/lib_plugin/mempool.ml @@ -549,7 +549,7 @@ let pre_filter info config | Single (Failing_noop _) -> return (`Refused [Environment.wrap_tzerror Wrong_operation]) | Single (Preattestation consensus_content) - | Single (Attestation consensus_content) -> + | Single (Attestation {consensus_content; dal_content = _}) -> let level_and_round : level_and_round = {level = consensus_content.level; round = consensus_content.round} in diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 9db99c9a6e0e..982aef8efe7c 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -4445,6 +4445,8 @@ val consensus_content_encoding : consensus_content Data_encoding.t val pp_consensus_content : Format.formatter -> consensus_content -> unit +type dal_content = {attestation : Dal.Attestation.t} + type 'kind operation = { shell : Operation.shell_header; protocol_data : 'kind protocol_data; @@ -4463,7 +4465,11 @@ and _ contents_list = and _ contents = | Preattestation : consensus_content -> Kind.preattestation contents - | Attestation : consensus_content -> Kind.attestation contents + | Attestation : { + consensus_content : consensus_content; + dal_content : dal_content option; + } + -> Kind.attestation contents | Dal_attestation : Dal.Attestation.operation -> Kind.dal_attestation contents | Seed_nonce_revelation : { level : Raw_level.t; @@ -4751,6 +4757,10 @@ module Operation : sig val attestation_case : Kind.attestation case + val endorsement_with_dal_case : Kind.attestation case + + val attestation_with_dal_case : Kind.attestation case + val dal_attestation_case : Kind.dal_attestation case val seed_nonce_revelation_case : Kind.seed_nonce_revelation case diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 857160c3592c..54b4204f58aa 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2374,7 +2374,8 @@ let punish_double_attestation_or_preattestation (type kind) ctxt ~operation_hash Double_attestation_evidence_result {forbidden_delegate; balance_updates} in match op1.protocol_data.contents with - | Single (Preattestation e1) | Single (Attestation e1) -> + | Single (Preattestation e1) + | Single (Attestation {consensus_content = e1; dal_content = _}) -> let level = Level.from_raw ctxt e1.level in let* ctxt, consensus_pk1 = Stake_distribution.slot_owner ctxt level e1.slot @@ -2421,7 +2422,7 @@ let apply_contents_list (type kind) ctxt chain_id (mode : mode) match contents_list with | Single (Preattestation consensus_content) -> record_preattestation ctxt mode consensus_content - | Single (Attestation consensus_content) -> + | Single (Attestation {consensus_content; dal_content = _ (* TODO *)}) -> record_attestation ctxt mode consensus_content | Single (Dal_attestation op) -> (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3115 diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index f2aa020fb079..9901c0ddeaa1 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -1150,7 +1150,9 @@ module Encoding = struct | Contents_result (Attestation_result _ as op) -> Some op | _ -> None); mselect = (function - | Contents_and_result ((Attestation _ as op), res) -> Some (op, res) + | Contents_and_result + ((Attestation {dal_content = None; _} as op), res) -> + Some (op, res) | _ -> None); proj = (function @@ -1173,7 +1175,59 @@ module Encoding = struct | Contents_result (Attestation_result _ as op) -> Some op | _ -> None); mselect = (function - | Contents_and_result ((Attestation _ as op), res) -> Some (op, res) + | Contents_and_result + ((Attestation {dal_content = None; _} as op), res) -> + Some (op, res) + | _ -> None); + proj = + (function + | Attestation_result + {balance_updates; delegate; consensus_key; consensus_power} -> + (balance_updates, delegate, consensus_power, consensus_key)); + inj = + (fun (balance_updates, delegate, consensus_power, consensus_key) -> + Attestation_result + {balance_updates; delegate; consensus_key; consensus_power}); + } + + let endorsement_with_dal_case = + Case + { + op_case = Operation.Encoding.endorsement_with_dal_case; + encoding = consensus_result_encoding_legacy "endorsement"; + select = + (function + | Contents_result (Attestation_result _ as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result + ((Attestation {dal_content = Some _; _} as op), res) -> + Some (op, res) + | _ -> None); + proj = + (function + | Attestation_result + {balance_updates; delegate; consensus_key; consensus_power} -> + (balance_updates, delegate, consensus_power, consensus_key)); + inj = + (fun (balance_updates, delegate, consensus_power, consensus_key) -> + Attestation_result + {balance_updates; delegate; consensus_key; consensus_power}); + } + + let attestation_with_dal_case = + Case + { + op_case = Operation.Encoding.attestation_with_dal_case; + encoding = consensus_result_encoding; + select = + (function + | Contents_result (Attestation_result _ as op) -> Some op | _ -> None); + mselect = + (function + | Contents_and_result + ((Attestation {dal_content = Some _; _} as op), res) -> + Some (op, res) | _ -> None); proj = (function @@ -1844,13 +1898,15 @@ let common_cases = let contents_cases = let open Encoding in - attestation_case :: preattestation_case :: double_attestation_evidence_case - :: double_preattestation_evidence_case :: common_cases + attestation_case :: attestation_with_dal_case :: preattestation_case + :: double_attestation_evidence_case :: double_preattestation_evidence_case + :: common_cases let contents_cases_with_legacy_attestation_name = let open Encoding in - endorsement_case :: preendorsement_case :: double_endorsement_evidence_case - :: double_preendorsement_evidence_case :: common_cases + endorsement_case :: endorsement_with_dal_case :: preendorsement_case + :: double_endorsement_evidence_case :: double_preendorsement_evidence_case + :: common_cases let make_contents_result (Encoding.Case diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index ab0cbb700c6c..a31152f072e8 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -155,6 +155,8 @@ type consensus_content = { important but could make things easier for debugging *) } +type dal_content = {attestation : Dal_attestation_repr.t} + let consensus_content_encoding = let open Data_encoding in conv @@ -238,7 +240,11 @@ and _ contents_list = and _ contents = | Preattestation : consensus_content -> Kind.preattestation contents - | Attestation : consensus_content -> Kind.attestation contents + | Attestation : { + consensus_content : consensus_content; + dal_content : dal_content option; + } + -> Kind.attestation contents | Dal_attestation : Dal_attestation_repr.operation -> Kind.dal_attestation contents @@ -1103,13 +1109,56 @@ module Encoding = struct @@ union [make preattestation_case])) (varopt "signature" Signature.encoding))) - let endorsement_encoding = + let consensus_content_encoding = obj4 (req "slot" Slot_repr.encoding) (req "level" Raw_level_repr.encoding) (req "round" Round_repr.encoding) (req "block_payload_hash" Block_payload_hash.encoding) + let dal_content_encoding = + obj1 (req "dal_attestation" Dal_attestation_repr.encoding) + + let endorsement_encoding = consensus_content_encoding + + let endorsement_with_dal_encoding = + merge_objs consensus_content_encoding dal_content_encoding + + (* Precondition: [dal_content = None]. *) + let attestation_encoding_proj + (Attestation {consensus_content; dal_content = _}) = + ( consensus_content.slot, + consensus_content.level, + consensus_content.round, + consensus_content.block_payload_hash ) + + let attestation_encoding_inj (slot, level, round, block_payload_hash) = + Attestation + { + consensus_content = {slot; level; round; block_payload_hash}; + dal_content = None; + } + + (* Precondition: [dal_content <> None]. Check usage! *) + let attestation_with_dal_encoding_proj + (Attestation {consensus_content; dal_content}) = + match dal_content with + | None -> assert false + | Some dal_content -> + ( ( consensus_content.slot, + consensus_content.level, + consensus_content.round, + consensus_content.block_payload_hash ), + dal_content.attestation ) + + let attestation_with_dal_encoding_inj + ((slot, level, round, block_payload_hash), attestation) = + Attestation + { + consensus_content = {slot; level; round; block_payload_hash}; + dal_content = Some {attestation}; + } + (* Encoding case that accepts legacy attestation name : `endorsement` in JSON https://gitlab.com/tezos/tezos/-/issues/5529 @@ -1124,16 +1173,11 @@ module Encoding = struct name = "endorsement"; encoding = endorsement_encoding; select = - (function Contents (Attestation _ as op) -> Some op | _ -> None); - proj = - (fun (Attestation consensus_content) -> - ( consensus_content.slot, - consensus_content.level, - consensus_content.round, - consensus_content.block_payload_hash )); - inj = - (fun (slot, level, round, block_payload_hash) -> - Attestation {slot; level; round; block_payload_hash}); + (function + | Contents (Attestation {dal_content = None; _} as op) -> Some op + | _ -> None); + proj = attestation_encoding_proj; + inj = attestation_encoding_inj; } let attestation_case = @@ -1143,16 +1187,39 @@ module Encoding = struct name = "attestation"; encoding = endorsement_encoding; select = - (function Contents (Attestation _ as op) -> Some op | _ -> None); - proj = - (fun (Attestation consensus_content) -> - ( consensus_content.slot, - consensus_content.level, - consensus_content.round, - consensus_content.block_payload_hash )); - inj = - (fun (slot, level, round, block_payload_hash) -> - Attestation {slot; level; round; block_payload_hash}); + (function + | Contents (Attestation {dal_content = None; _} as op) -> Some op + | _ -> None); + proj = attestation_encoding_proj; + inj = attestation_encoding_inj; + } + + let endorsement_with_dal_case = + Case + { + tag = 23; + name = "endorsement_with_dal"; + encoding = endorsement_with_dal_encoding; + select = + (function + | Contents (Attestation {dal_content = Some _; _} as op) -> Some op + | _ -> None); + proj = attestation_with_dal_encoding_proj; + inj = attestation_with_dal_encoding_inj; + } + + let attestation_with_dal_case = + Case + { + tag = 23; + name = "attestation_with_dal"; + encoding = endorsement_with_dal_encoding; + select = + (function + | Contents (Attestation {dal_content = Some _; _} as op) -> Some op + | _ -> None); + proj = attestation_with_dal_encoding_proj; + inj = attestation_with_dal_encoding_inj; } (* Encoding that accepts legacy attestation name : `endorsement` in JSON @@ -1162,10 +1229,21 @@ module Encoding = struct This encoding is temporary and should be removed when the endorsements kinds in JSON will not be accepted any more by the protocol (Planned for protocol Q). *) - let endorsement_encoding = - let make (Case {tag; name; encoding; select = _; proj; inj}) = - case (Tag tag) name encoding (fun o -> Some (proj o)) (fun x -> inj x) + let make kind (Case {tag; name; encoding; select = _; proj; inj}) = + case + (Tag tag) + name + encoding + (function + | o -> ( + match (kind, o) with + | `Simple, (Attestation {dal_content = None; _} as op) -> + Some (proj op) + | `Full, (Attestation {dal_content = Some _; _} as op) -> + Some (proj op) + | _ -> None)) + (fun x -> inj x) in let to_list : Kind.attestation contents_list -> _ = fun (Single o) -> o in let of_list : Kind.attestation contents -> _ = fun o -> Single o in @@ -1182,12 +1260,28 @@ module Encoding = struct "operations" (conv to_list of_list @@ def "inlined.endorsement_mempool.contents" - @@ union [make endorsement_case])) + @@ union + [ + make `Simple endorsement_case; + make `Full endorsement_with_dal_case; + ])) (varopt "signature" Signature.encoding))) let attestation_encoding = - let make (Case {tag; name; encoding; select = _; proj; inj}) = - case (Tag tag) name encoding (fun o -> Some (proj o)) (fun x -> inj x) + let make kind (Case {tag; name; encoding; select = _; proj; inj}) = + case + (Tag tag) + name + encoding + (function + | o -> ( + match (kind, o) with + | `Without_dal, (Attestation {dal_content = None; _} as op) -> + Some (proj op) + | `With_dal, (Attestation {dal_content = Some _; _} as op) -> + Some (proj op) + | _ -> None)) + (fun x -> inj x) in let to_list : Kind.attestation contents_list -> _ = fun (Single o) -> o in let of_list : Kind.attestation contents -> _ = fun o -> Single o in @@ -1204,7 +1298,11 @@ module Encoding = struct "operations" (conv to_list of_list @@ def "inlined.attestation_mempool.contents" - @@ union [make attestation_case])) + @@ union + [ + make `Without_dal attestation_case; + make `With_dal attestation_with_dal_case; + ])) (varopt "signature" Signature.encoding))) let dal_attestation_encoding = @@ -1622,6 +1720,7 @@ module Encoding = struct let contents_cases = PCase preattestation_case :: PCase attestation_case + :: PCase attestation_with_dal_case :: PCase double_preattestation_evidence_case :: PCase double_attestation_evidence_case :: common_cases @@ -1635,6 +1734,7 @@ module Encoding = struct protocol Q). *) let contents_cases_with_legacy_attestation_name = PCase preendorsement_case :: PCase endorsement_case + :: PCase endorsement_with_dal_case :: PCase double_preendorsement_evidence_case :: PCase double_endorsement_evidence_case :: common_cases @@ -2423,7 +2523,7 @@ let weight_of : packed_operation -> operation_weight = ( Consensus, Weight_preattestation (attestation_infos_from_consensus_content consensus_content) ) - | Single (Attestation consensus_content) -> + | Single (Attestation {consensus_content; dal_content = _ (* TODO *)}) -> W ( Consensus, Weight_attestation @@ -2443,7 +2543,7 @@ let weight_of : packed_operation -> operation_weight = W (Anonymous, Weight_vdf_revelation solution) | Single (Double_attestation_evidence {op1; _}) -> ( match op1.protocol_data.contents with - | Single (Attestation consensus_content) -> + | Single (Attestation {consensus_content; dal_content = _ (* TODO *)}) -> W ( Anonymous, Weight_double_attestation diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index fb56832141b2..9ef1451b5048 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -190,6 +190,8 @@ val consensus_content_encoding : consensus_content Data_encoding.t val pp_consensus_content : Format.formatter -> consensus_content -> unit +type dal_content = {attestation : Dal_attestation_repr.t} + type consensus_watermark = | Attestation of Chain_id.t | Preattestation of Chain_id.t @@ -236,7 +238,11 @@ and _ contents = | Preattestation : consensus_content -> Kind.preattestation contents (* Attestation: About consensus, attestation of a block held by a validator. *) - | Attestation : consensus_content -> Kind.attestation contents + | Attestation : { + consensus_content : consensus_content; + dal_content : dal_content option; + } + -> Kind.attestation contents (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3115 Temporary operation to avoid modifying attestation encoding. *) @@ -687,6 +693,10 @@ module Encoding : sig val attestation_case : Kind.attestation case + val endorsement_with_dal_case : Kind.attestation case + + val attestation_with_dal_case : Kind.attestation case + val dal_attestation_case : Kind.dal_attestation case val seed_nonce_revelation_case : Kind.seed_nonce_revelation case diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index c98b8379282d..152bd16a0bfb 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -97,8 +97,8 @@ let mk_consensus_content_signer_and_branch ?delegate ?slot ?level ?round let* signer = Account.find delegate_pkh in return (consensus_content, signer.sk, branch) -let raw_attestation ?delegate ?slot ?level ?round ?block_payload_hash ?branch - attested_block = +let raw_attestation ?delegate ?slot ?level ?round ?block_payload_hash + ?dal_content ?branch attested_block = let open Lwt_result_syntax in let* consensus_content, signer, branch = mk_consensus_content_signer_and_branch @@ -110,7 +110,7 @@ let raw_attestation ?delegate ?slot ?level ?round ?block_payload_hash ?branch ?branch attested_block in - let op = Single (Attestation consensus_content) in + let op = Single (Attestation {consensus_content; dal_content}) in return (sign ~watermark:Operation.(to_watermark (Attestation Chain_id.zero)) @@ -118,8 +118,8 @@ let raw_attestation ?delegate ?slot ?level ?round ?block_payload_hash ?branch branch op) -let attestation ?delegate ?slot ?level ?round ?block_payload_hash ?branch - attested_block = +let attestation ?delegate ?slot ?level ?round ?block_payload_hash ?dal_content + ?branch attested_block = let open Lwt_result_syntax in let* op = raw_attestation @@ -128,6 +128,7 @@ let attestation ?delegate ?slot ?level ?round ?block_payload_hash ?branch ?level ?round ?block_payload_hash + ?dal_content ?branch attested_block in diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index adea59f7c646..da972eec3e15 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -54,7 +54,7 @@ val sign : (** Create an unpacked attestation that is expected for given [Block.t]. Optional parameters allow to specify the attested values: [level], - [round] and/or [block_payload_hash]. + [round], [block_payload_hash], and/or [dal_content]. They also allow to specify the attester ([delegate]), and/or the [slot]. These default to the first slot and its delegate. @@ -67,6 +67,7 @@ val raw_attestation : ?level:Raw_level.t -> ?round:Round.t -> ?block_payload_hash:Block_payload_hash.t -> + ?dal_content:dal_content -> ?branch:Block_hash.t -> Block.t -> Kind.attestation Operation.t tzresult Lwt.t @@ -93,6 +94,7 @@ val attestation : ?level:Raw_level.t -> ?round:Round.t -> ?block_payload_hash:Block_payload_hash.t -> + ?dal_content:dal_content -> ?branch:Block_hash.t -> Block.t -> Operation.packed tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/helpers/operation_generator.ml b/src/proto_alpha/lib_protocol/test/helpers/operation_generator.ml index 59f46b49d293..bcd0d6b10008 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/operation_generator.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/operation_generator.ml @@ -386,7 +386,7 @@ let generate_preattestation = let generate_attestation = let open QCheck2.Gen in let+ cc = generate_consensus_content in - Attestation cc + Attestation {consensus_content = cc; dal_content = None} let generate_dal_attestation = let open QCheck2.Gen in 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 1ef41b60577b..d3009d5e7fff 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 @@ -588,7 +588,7 @@ let test_no_conflict_various_levels_and_rounds () = let (Operation_data protocol_data) = op.protocol_data in let content = match protocol_data.contents with - | Single (Attestation content) -> content + | Single (Attestation {consensus_content = content; _}) -> content | _ -> assert false in Format.eprintf diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 963a48d0aa9c..89f0b9a25a40 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -730,7 +730,7 @@ module Consensus = struct ~error:(trace_of_error Consensus_operation_not_allowed) vi.consensus_info in - let (Single (Attestation consensus_content)) = + let (Single (Attestation {consensus_content; dal_content = _ (* TODO *)})) = operation.protocol_data.contents in let* consensus_key, voting_power = @@ -756,7 +756,9 @@ module Consensus = struct let check_attestation_conflict vs oph (operation : Kind.attestation operation) = - let (Single (Attestation {slot; level; round; _})) = + let (Single + (Attestation + {consensus_content = {slot; level; round; _}; dal_content = _})) = operation.protocol_data.contents in match @@ -776,7 +778,9 @@ module Consensus = struct Conflicting_consensus_operation {kind = Attestation; conflict}) let add_attestation vs oph (op : Kind.attestation operation) = - let (Single (Attestation {slot; level; round; _})) = + let (Single + (Attestation + {consensus_content = {slot; level; round; _}; dal_content = _})) = op.protocol_data.contents in let attestations_seen = @@ -800,7 +804,9 @@ module Consensus = struct let remove_attestation vs (operation : Kind.attestation operation) = (* We do not remove the attestation power because it is not relevant for the mempool mode. *) - let (Single (Attestation {slot; level; round; _})) = + let (Single + (Attestation + {consensus_content = {slot; level; round; _}; dal_content = _})) = operation.protocol_data.contents in let attestations_seen = @@ -1383,7 +1389,8 @@ module Anonymous = struct let open Lwt_result_syntax in match (op1.protocol_data.contents, op2.protocol_data.contents) with | Single (Preattestation e1), Single (Preattestation e2) - | Single (Attestation e1), Single (Attestation e2) -> + | ( Single (Attestation {consensus_content = e1; dal_content = _}), + Single (Attestation {consensus_content = e2; dal_content = _}) ) -> let op1_hash = Operation.hash op1 in let op2_hash = Operation.hash op2 in let same_levels = Raw_level.(e1.level = e2.level) in @@ -1471,7 +1478,8 @@ module Anonymous = struct let check_double_attesting_evidence_conflict (type kind) vs oph (op1 : kind Kind.consensus Operation.t) = match op1.protocol_data.contents with - | Single (Preattestation e1) | Single (Attestation e1) -> ( + | Single (Preattestation e1) + | Single (Attestation {consensus_content = e1; dal_content = _}) -> ( match Double_attesting_evidence_map.find (e1.level, e1.round, e1.slot) @@ -1502,7 +1510,8 @@ module Anonymous = struct let add_double_attesting_evidence (type kind) vs oph (op1 : kind Kind.consensus Operation.t) = match op1.protocol_data.contents with - | Single (Preattestation e1) | Single (Attestation e1) -> + | Single (Preattestation e1) + | Single (Attestation {consensus_content = e1; dal_content = _}) -> let double_attesting_evidences_seen = Double_attesting_evidence_map.add (e1.level, e1.round, e1.slot) @@ -1532,7 +1541,8 @@ module Anonymous = struct let remove_double_attesting_evidence (type kind) vs (op : kind Kind.consensus Operation.t) = match op.protocol_data.contents with - | Single (Attestation e) | Single (Preattestation e) -> + | Single (Attestation {consensus_content = e; dal_content = _}) + | Single (Preattestation e) -> let double_attesting_evidences_seen = Double_attesting_evidence_map.remove (e.level, e.round, e.slot) -- GitLab From e4fd390ec7bb05e47498cf9bc4299a7aea658644 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 16 Jan 2024 14:56:20 +0100 Subject: [PATCH 02/17] Alpha: refactor consensus op comparison --- .../lib_protocol/operation_repr.ml | 83 +++++++------------ 1 file changed, 28 insertions(+), 55 deletions(-) diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index a31152f072e8..1a83462a6744 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -2571,34 +2571,31 @@ let weight_of : packed_operation -> operation_weight = let manweight, src = weight_manager ops in W (Manager, Weight_manager (manweight, src)) -(** {3 Comparisons of operations {!weight}} *) +(** {3 Comparisons of operations' {!weight}} *) (** {4 Helpers} *) -(** compare a pair of elements in lexicographic order. *) +(** Compare a pair of elements in lexicographic order. *) let compare_pair_in_lexico_order ~cmp_fst ~cmp_snd (a1, b1) (a2, b2) = let resa = cmp_fst a1 a2 in if Compare.Int.(resa <> 0) then resa else cmp_snd b1 b2 -(** compare in reverse order. *) +(** Compare in reverse order. *) let compare_reverse (cmp : 'a -> 'a -> int) a b = cmp b a (** {4 Comparison of {!consensus_infos}} *) -(** Two {!round_infos} compares as the pair of [level, round] in +(** Two {!round_infos} pairs [(level, round)] compare in lexicographic order: the one with the greater [level] being the greater [round_infos]. When levels are the same, the one with the greater [round] being the better. - The greater {!round_infos} is the farther to the current state + The better {!round_infos} is farther to the current state when part of the weight of a valid consensus operation. - The best {!round_infos} is the nearer to the current state when + The better {!round_infos} is nearer to the current state when part of the weight of a valid denunciation. - In both case, that is the greater according to the lexicographic - order. - Precondition: the {!round_infos} are from valid operation. They have been computed by either {!round_infos_from_consensus_content} or {!consensus_infos_and_hash_from_block_header}. Both input @@ -2612,40 +2609,14 @@ let compare_round_infos (infos1 : round_infos) (infos2 : round_infos) = (infos1.level, infos1.round) (infos2.level, infos2.round) -(** When comparing {!Attestation} to {!Preattestation} or - {!Double_attestation_evidence} to {!Double_preattestation}, in case - of {!round_infos} equality, the position is relevant to compute the - order. *) -type prioritized_position = Nopos | Fstpos | Sndpos - -(** Comparison of two {!round_infos} with priority in case of - {!round_infos} equality. *) -let compare_round_infos_with_prioritized_position ~prioritized_position infos1 - infos2 = - let cmp = compare_round_infos infos1 infos2 in - if Compare.Int.(cmp <> 0) then cmp - else match prioritized_position with Fstpos -> 1 | Sndpos -> -1 | Nopos -> 0 - -(** When comparing consensus operation with {!attestation_infos}, in - case of equality of their {!round_infos}, either they are of the - same kind and their [slot] have to be compared in the reverse - order, otherwise the {!Attestation} is better and - [prioritized_position] gives its position. *) -let compare_prioritized_position_or_slot ~prioritized_position = - match prioritized_position with - | Nopos -> compare_reverse Compare.Int.compare - | Fstpos -> fun _ _ -> 1 - | Sndpos -> fun _ _ -> -1 - (** Two {!attestation_infos} are compared by their {!round_infos}. When their {!round_infos} are equal, they are compared according to - their priority or their [slot], see - {!compare_prioritized_position_or_slot} for more details. *) -let compare_attestation_infos ~prioritized_position (infos1 : attestation_infos) + their [slot]: the smaller the better. *) +let compare_attestation_infos (infos1 : attestation_infos) (infos2 : attestation_infos) = compare_pair_in_lexico_order ~cmp_fst:compare_round_infos - ~cmp_snd:(compare_prioritized_position_or_slot ~prioritized_position) + ~cmp_snd:(compare_reverse Compare.Int.compare) (infos1.round, infos1.slot) (infos2.round, infos2.slot) @@ -2679,9 +2650,11 @@ let compare_dal_attestation_infos (** {5 Comparison of valid consensus operations} *) -(** Comparing consensus operations by their [weight] uses the - comparison on {!attestation_infos} for {!Attestation} and - {!Preattestation}: see {!attestation_infos} for more details. +(** Comparing consensus operations by their [weight] uses the comparison on + {!attestation_infos} for {!Attestation} and {!Preattestation}. In case of + equality of their {!round_infos}, either they are of the same kind and their + [slot]s have to be compared in the reverse order, otherwise the + {!Attestation}s are better. {!Dal_attestation} is smaller than the other kinds of consensus operations. Two valid {!Dal_attestation} are @@ -2689,13 +2662,17 @@ let compare_dal_attestation_infos let compare_consensus_weight w1 w2 = match (w1, w2) with | Weight_attestation infos1, Weight_attestation infos2 -> - compare_attestation_infos ~prioritized_position:Nopos infos1 infos2 + compare_attestation_infos infos1 infos2 | Weight_preattestation infos1, Weight_preattestation infos2 -> - compare_attestation_infos ~prioritized_position:Nopos infos1 infos2 - | Weight_attestation infos1, Weight_preattestation infos2 -> - compare_attestation_infos ~prioritized_position:Fstpos infos1 infos2 - | Weight_preattestation infos1, Weight_attestation infos2 -> - compare_attestation_infos ~prioritized_position:Sndpos infos1 infos2 + compare_attestation_infos infos1 infos2 + | ( Weight_attestation {round = round_infos1; _}, + Weight_preattestation {round = round_infos2; _} ) -> + let cmp = compare_round_infos round_infos1 round_infos2 in + if Compare.Int.(cmp <> 0) then cmp else 1 + | ( Weight_preattestation {round = round_infos1; _}, + Weight_attestation {round = round_infos2; _} ) -> + let cmp = compare_round_infos round_infos1 round_infos2 in + if Compare.Int.(cmp <> 0) then cmp else -1 | Weight_dal_attestation infos1, Weight_dal_attestation infos2 -> compare_dal_attestation_infos infos1 infos2 | Weight_dal_attestation _, (Weight_attestation _ | Weight_preattestation _) @@ -2753,15 +2730,11 @@ let compare_anonymous_weight w1 w2 = | Weight_double_preattestation infos1, Weight_double_preattestation infos2 -> compare_round_infos infos1 infos2 | Weight_double_preattestation infos1, Weight_double_attestation infos2 -> - compare_round_infos_with_prioritized_position - ~prioritized_position:Fstpos - infos1 - infos2 + let cmp = compare_round_infos infos1 infos2 in + if Compare.Int.(cmp <> 0) then cmp else 1 | Weight_double_attestation infos1, Weight_double_preattestation infos2 -> - compare_round_infos_with_prioritized_position - ~prioritized_position:Sndpos - infos1 - infos2 + let cmp = compare_round_infos infos1 infos2 in + if Compare.Int.(cmp <> 0) then cmp else -1 | Weight_double_attestation infos1, Weight_double_attestation infos2 -> compare_round_infos infos1 infos2 | ( ( Weight_double_baking _ | Weight_seed_nonce_revelation _ -- GitLab From d92eceafcdb917ae3b1c53ef4498d28f9baaedae Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Tue, 16 Jan 2024 14:56:52 +0100 Subject: [PATCH 03/17] Alpha/DAL: take into account DAL content for attestations' weight --- .../lib_protocol/operation_repr.ml | 88 +++++++++++++------ .../lib_protocol/operation_repr.mli | 17 ++-- 2 files changed, 70 insertions(+), 35 deletions(-) diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 1a83462a6744..674fea38cf61 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -2308,17 +2308,21 @@ let compare_inner_pass : type a b. a pass -> b pass -> int = failed to convert in a {!int}, the value of [round] is (-1). *) type round_infos = {level : int32; round : int} -(** [attestation_infos] is the pair of a {!round_infos} and a [slot] +(** [preattestation_infos] is the pair of a {!round_infos} and a [slot] convert into an {!int}. *) -type attestation_infos = {round : round_infos; slot : int} +type preattestation_infos = {round : round_infos; slot : int} -(** [dal_attestation_infos] gives the weight of a DAL attestation. *) -type dal_attestation_infos = { +(** [attestation_infos] is the tuple consisting of a {!round_infos} value, a + [slot], and the number of DAL slots in the DAL attestation. *) +type attestation_infos = { round_infos : round_infos; slot : int; number_of_attested_slots : int; } +(** [dal_attestation_infos] gives the weight of a DAL attestation. *) +type dal_attestation_infos = attestation_infos + (** [double_baking_infos] is the pair of a {!round_infos} and a {!block_header} hash. *) type double_baking_infos = {round : round_infos; bh_hash : Block_hash.t} @@ -2349,6 +2353,31 @@ let attestation_infos_from_consensus_content (c : consensus_content) = let round = round_infos_from_consensus_content c in {round; slot} +(** Compute a {!attestation_infos} value from a {!consensus_content} value + and an optional {!dal_content} value. It is used to compute the weight of + an {!Attestation}. + + An {!Attestation} with no DAL content or with a DAL content that has 0 + attested DAL slots have the same weight (everything else being + equal). That's ok, because they are semantically equal, therefore it + does not matter which one is picked. + + Precondition: [c] and [d] come from a valid operation. *) +let attestation_infos_from_content (c : consensus_content) + (d : dal_content option) = + let slot = Slot_repr.to_int c.slot in + let round_infos = round_infos_from_consensus_content c in + { + round_infos; + slot; + number_of_attested_slots = + Option.fold + ~none:0 + ~some:(fun d -> + Dal_attestation_repr.number_of_attested_slots d.attestation) + d; + } + let dal_attestation_infos_from_dal_operation {Dal_attestation_repr.attestation; level; round; slot} = let round_infos = @@ -2394,12 +2423,12 @@ let consensus_infos_and_hash_from_block_header (bh : Block_header_repr.t) = is used to compare it to an operation of the same pass. Operation weight are defined by validation pass. - The [weight] of an {!Attestation} or {!Preattestation} depends on - its {!attestation_infos}. + The [weight] of an {!Attestation} or {!Preattestation} depends on its + {!attestation_infos}. For {!Attestation}s it also depends on the number of + attested DAL slots. - The [weight] of a {!Dal_attestation} depends on the pair of - the size of its bitset, {!Dal_attestation_repr.t}, and the - signature of its attester {! Signature.Public_key_hash.t}. + The [weight] of a {!Dal_attestation} is the same as that of an + {!Attestation}. The [weight] of a voting operation depends on the pair of its [period] and [source]. @@ -2428,7 +2457,7 @@ let consensus_infos_and_hash_from_block_header (bh : Block_header_repr.t) = [gas_limit] ratio expressed in {!Q.t}. *) type _ weight = | Weight_attestation : attestation_infos -> consensus_pass_type weight - | Weight_preattestation : attestation_infos -> consensus_pass_type weight + | Weight_preattestation : preattestation_infos -> consensus_pass_type weight | Weight_dal_attestation : dal_attestation_infos -> consensus_pass_type weight | Weight_proposals : int32 * Signature.Public_key_hash.t @@ -2523,11 +2552,11 @@ let weight_of : packed_operation -> operation_weight = ( Consensus, Weight_preattestation (attestation_infos_from_consensus_content consensus_content) ) - | Single (Attestation {consensus_content; dal_content = _ (* TODO *)}) -> + | Single (Attestation {consensus_content; dal_content}) -> W ( Consensus, Weight_attestation - (attestation_infos_from_consensus_content consensus_content) ) + (attestation_infos_from_content consensus_content dal_content) ) | Single (Dal_attestation content) -> W ( Consensus, @@ -2543,7 +2572,7 @@ let weight_of : packed_operation -> operation_weight = W (Anonymous, Weight_vdf_revelation solution) | Single (Double_attestation_evidence {op1; _}) -> ( match op1.protocol_data.contents with - | Single (Attestation {consensus_content; dal_content = _ (* TODO *)}) -> + | Single (Attestation {consensus_content; dal_content = _}) -> W ( Anonymous, Weight_double_attestation @@ -2609,11 +2638,11 @@ let compare_round_infos (infos1 : round_infos) (infos2 : round_infos) = (infos1.level, infos1.round) (infos2.level, infos2.round) -(** Two {!attestation_infos} are compared by their {!round_infos}. +(** Two {!Preattestation}s are compared by their {!preattestation_infos}. When their {!round_infos} are equal, they are compared according to their [slot]: the smaller the better. *) -let compare_attestation_infos (infos1 : attestation_infos) - (infos2 : attestation_infos) = +let compare_preattestation_infos (infos1 : preattestation_infos) + (infos2 : preattestation_infos) = compare_pair_in_lexico_order ~cmp_fst:compare_round_infos ~cmp_snd:(compare_reverse Compare.Int.compare) @@ -2630,11 +2659,11 @@ let compare_baking_infos infos1 infos2 = (infos1.round, infos1.bh_hash) (infos2.round, infos2.bh_hash) -(** Two valid {!Dal_attestation} are compared in the lexicographic order of - their level, round, reverse slot, and number of attested slots, meaning - that, in order, higher level is better, higher round is better, smaller slot - is better, higher number of attested slots is better. *) -let compare_dal_attestation_infos +(** Two {!Attestation}s are compared by their {!attestation_infos}. When their + {!round_infos} are equal, they are compared according to their [slot]: the + smaller the better. When the slots are also equal they are compared + according to the number of attested DAL slots: the more the better. *) +let compare_attestation_infos {round_infos = infos1; slot = slot1; number_of_attested_slots = n1} {round_infos = infos2; slot = slot2; number_of_attested_slots = n2} = compare_pair_in_lexico_order @@ -2646,15 +2675,22 @@ let compare_dal_attestation_infos ((infos1, slot1), n1) ((infos2, slot2), n2) +(** Two valid {!Dal_attestation} are compared in the lexicographic order of + their level, round, reverse slot, and number of attested slots, meaning + that, in order, higher level is better, higher round is better, smaller slot + is better, higher number of attested slots is better. *) +let compare_dal_attestation_infos = compare_attestation_infos + (** {4 Comparison of valid operations of the same validation pass} *) (** {5 Comparison of valid consensus operations} *) (** Comparing consensus operations by their [weight] uses the comparison on - {!attestation_infos} for {!Attestation} and {!Preattestation}. In case of + {!attestation_infos} for {!Attestation}s and {!Preattestation}s. In case of equality of their {!round_infos}, either they are of the same kind and their [slot]s have to be compared in the reverse order, otherwise the - {!Attestation}s are better. + {!Attestation}s are better. In case of {!Attestation}s, the number of + attested DAL slots is taken into account when all else is equal. {!Dal_attestation} is smaller than the other kinds of consensus operations. Two valid {!Dal_attestation} are @@ -2664,13 +2700,13 @@ let compare_consensus_weight w1 w2 = | Weight_attestation infos1, Weight_attestation infos2 -> compare_attestation_infos infos1 infos2 | Weight_preattestation infos1, Weight_preattestation infos2 -> - compare_attestation_infos infos1 infos2 - | ( Weight_attestation {round = round_infos1; _}, + compare_preattestation_infos infos1 infos2 + | ( Weight_attestation {round_infos = round_infos1; _}, Weight_preattestation {round = round_infos2; _} ) -> let cmp = compare_round_infos round_infos1 round_infos2 in if Compare.Int.(cmp <> 0) then cmp else 1 | ( Weight_preattestation {round = round_infos1; _}, - Weight_attestation {round = round_infos2; _} ) -> + Weight_attestation {round_infos = round_infos2; _} ) -> let cmp = compare_round_infos round_infos1 round_infos2 in if Compare.Int.(cmp <> 0) then cmp else -1 | Weight_dal_attestation infos1, Weight_dal_attestation infos2 -> diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index 9ef1451b5048..0f48611aa3b3 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -616,15 +616,14 @@ val compare_by_passes : packed_operation -> packed_operation -> int {!Vdf_revelation} > {!Seed_nonce_revelation} > {!Activate_account} > {!Drain_delegate} > {!Manager_operation}. - {!Attestation} and {!Preattestation} are compared by the pair of - their [level] and [round] such as the farther to the current state - [level] and [round] is greater; e.g. the greater pair in - lexicographic order being the better. When equal and both - operations being of the same kind, we compare their [slot]: the - The smaller being the better, assuming that the more slots an attester - has, the smaller is its smallest [slot]. When the pair is equal - and comparing an {!Attestation} to a {!Preattestation}, the - {!Attestation} is better. + {!Attestation} and {!Preattestation} are compared by the pair of their + [level] and [round] such as the farther to the current state [level] and + [round] is greater; e.g. the greater pair in lexicographic order being the + better. When equal and both operations being of the same kind, we compare + their [slot], the smaller being the better (assuming that the more slots an + attester has, the smaller is its smallest [slot]), and then the number of the + DAL attested slots, the more the better. When the pair is equal and comparing + an {!Attestation} to a {!Preattestation}, the {!Attestation} is better. Two {!Dal_attestation} ops are compared in the lexicographic order of the tuple of their level, their slot, their number of slots attested as -- GitLab From 1858e2f8a4b6138bb06eef17d4fc7c6245c1a9e3 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Mon, 15 Jan 2024 21:01:40 +0100 Subject: [PATCH 04/17] Alpha/DAL: validate the DAL content of an attestation --- src/proto_alpha/lib_protocol/dal_apply.ml | 19 +++++++++++++++- src/proto_alpha/lib_protocol/dal_apply.mli | 21 +++++++++++++++-- src/proto_alpha/lib_protocol/validate.ml | 26 ++++++++++++++++++---- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src/proto_alpha/lib_protocol/dal_apply.ml b/src/proto_alpha/lib_protocol/dal_apply.ml index 6e2f88994f7a..d636c421b068 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.ml +++ b/src/proto_alpha/lib_protocol/dal_apply.ml @@ -53,7 +53,24 @@ let slot_of_int_e ~number_of_slots n = let pkh_of_consensus_key (consensus_key : Consensus_key.pk) = consensus_key.delegate -let validate_attestation ctxt get_consensus_key_and_round_opt op = +let validate_attestation ctxt level 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 + 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 + let*? () = + error_unless + Compare.Int.(size <= maximum_size) + (Dal_attestation_size_limit_exceeded {maximum_size; got = size}) + in + let attester = pkh_of_consensus_key consensus_key in + fail_when + (Option.is_none @@ Dal.Attestation.shards_of_attester ctxt ~attester) + (Dal_data_availibility_attester_not_in_committee {attester; level}) + +let validate_dal_attestation ctxt get_consensus_key_and_round_opt op = let open Lwt_result_syntax in let*? () = assert_dal_feature_enabled ctxt in (* DAL/TODO: https://gitlab.com/tezos/tezos/-/issues/4462 diff --git a/src/proto_alpha/lib_protocol/dal_apply.mli b/src/proto_alpha/lib_protocol/dal_apply.mli index 8afef226cac2..2a8cbaca6caf 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.mli +++ b/src/proto_alpha/lib_protocol/dal_apply.mli @@ -28,16 +28,33 @@ open Alpha_context -(** [validate_attestation ctxt get_consensus_key_and_round op] checks whether +(** [validate_attestation ctxt level consensus_key attestation] checks whether + the DAL attestation [attestation] emitted at given [level] by the attester + with the given [consensus_key] 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_attestation : + t -> + Raw_level.t -> + Consensus_key.pk -> + Dal.Attestation.t -> + unit tzresult Lwt.t + +(** [validate_dal_attestation ctxt get_consensus_key_and_round op] checks whether the DAL attestation [op] 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 level as expected; * the round is as expected; * the delegate is in the DAL committee. [get_consensus_key_and_round_opt ()] returns the delegate that supposedly issued the attestation and optionally the round at which it was emitted. The round is not provided in the mempool validation mode. *) -val validate_attestation : +val validate_dal_attestation : t -> (unit -> (Consensus_key.pk * Round.t option) tzresult Lwt.t) -> Dal.Attestation.operation -> diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 89f0b9a25a40..96a1fcc2bda5 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -699,7 +699,7 @@ module Consensus = struct Return the slot owner's consensus key and voting power. *) let check_block_attestation vi consensus_info - {level; round; block_payload_hash = bph; slot} = + {level; round; block_payload_hash = bph; slot} dal_content_opt = let open Lwt_result_syntax in let*? expected_payload_hash = match Consensus.attestation_branch vi.ctxt with @@ -720,6 +720,17 @@ module Consensus = struct get_delegate_details consensus_info.attestation_slot_map kind slot 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 + level + consensus_key + dal.attestation) + dal_content_opt + in return (consensus_key, voting_power) let check_attestation vi ~check_signature @@ -730,13 +741,17 @@ module Consensus = struct ~error:(trace_of_error Consensus_operation_not_allowed) vi.consensus_info in - let (Single (Attestation {consensus_content; dal_content = _ (* TODO *)})) = + let (Single (Attestation {consensus_content; dal_content})) = operation.protocol_data.contents in let* consensus_key, voting_power = match vi.mode with | Application _ | Partial_validation _ | Construction _ -> - check_block_attestation vi consensus_info consensus_content + check_block_attestation + vi + consensus_info + consensus_content + dal_content | Mempool -> check_mempool_consensus vi @@ -850,7 +865,10 @@ module Consensus = struct in let* consensus_key = (* Note that this function checks the dal feature flag. *) - Dal_apply.validate_attestation vi.ctxt get_consensus_key_and_round_opt op + Dal_apply.validate_dal_attestation + vi.ctxt + get_consensus_key_and_round_opt + op in let*? () = if check_signature then -- GitLab From f2cc48a5fa9ac6678e7f8ce2a8b4bf9e740f0bca Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Mon, 15 Jan 2024 20:38:18 +0100 Subject: [PATCH 05/17] Alpha/DAL: apply the DAL content of an attestation --- src/proto_alpha/lib_protocol/apply.ml | 41 +++++++++++++++------- src/proto_alpha/lib_protocol/dal_apply.ml | 3 +- src/proto_alpha/lib_protocol/dal_apply.mli | 7 ++-- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 54b4204f58aa..b24c9eee5639 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2265,7 +2265,8 @@ let record_preattestation ctxt (mode : mode) (content : consensus_content) : in return (ctxt, mk_preattestation_result consensus_key 0 (* Fake power. *)) -let record_attestation ctxt (mode : mode) (content : consensus_content) : +let record_attestation ctxt (mode : mode) (consensus : consensus_content) + (dal : dal_content option) : (context * Kind.attestation contents_result_list) tzresult Lwt.t = let open Lwt_result_syntax in let mk_attestation_result ({delegate; consensus_pkh; _} : Consensus_key.pk) @@ -2282,10 +2283,21 @@ let record_attestation ctxt (mode : mode) (content : consensus_content) : match mode with | Application _ | Full_construction _ -> let*? consensus_key, power = - find_in_slot_map content.slot (Consensus.allowed_attestations ctxt) + find_in_slot_map consensus.slot (Consensus.allowed_attestations ctxt) in let*? ctxt = - Consensus.record_attestation ctxt ~initial_slot:content.slot ~power + Consensus.record_attestation ctxt ~initial_slot:consensus.slot ~power + in + let*? ctxt = + Option.fold + ~none:(Result_syntax.return ctxt) + ~some:(fun dal -> + Dal_apply.apply_attestation + ctxt + consensus_key + consensus.level + dal.attestation) + dal in return (ctxt, mk_attestation_result consensus_key power) | Partial_construction _ -> @@ -2297,8 +2309,8 @@ let record_attestation ctxt (mode : mode) (content : consensus_content) : attestations), but we don't need to, because there is no block to finalize anyway in this mode. *) let* ctxt, consensus_key = - let level = Level.from_raw ctxt content.level in - Stake_distribution.slot_owner ctxt level content.slot + let level = Level.from_raw ctxt consensus.level in + Stake_distribution.slot_owner ctxt level consensus.slot in return (ctxt, mk_attestation_result consensus_key 0 (* Fake power. *)) @@ -2422,9 +2434,9 @@ let apply_contents_list (type kind) ctxt chain_id (mode : mode) match contents_list with | Single (Preattestation consensus_content) -> record_preattestation ctxt mode consensus_content - | Single (Attestation {consensus_content; dal_content = _ (* TODO *)}) -> - record_attestation ctxt mode consensus_content - | Single (Dal_attestation op) -> + | Single (Attestation {consensus_content; dal_content}) -> + record_attestation ctxt mode consensus_content dal_content + | Single (Dal_attestation {level; attestation; slot; _}) -> (* DAL/FIXME https://gitlab.com/tezos/tezos/-/issues/3115 This is a temporary operation. This is done in order to avoid modifying @@ -2435,14 +2447,19 @@ let apply_contents_list (type kind) ctxt chain_id (mode : mode) match mode with | Application _ | Full_construction _ -> let*? consensus_key, _power = - find_in_slot_map op.slot (Consensus.allowed_attestations ctxt) + find_in_slot_map slot (Consensus.allowed_attestations ctxt) + in + let*? ctxt = + Dal_apply.apply_attestation ctxt consensus_key level attestation in return (ctxt, consensus_key) | Partial_construction _ -> - let level = Level.from_raw ctxt op.level in - Stake_distribution.slot_owner ctxt level op.slot + (* We do not record the DAL attestation for the same reason, we do + not record the consensus attestation; see reasoning in + {record_attestation}. *) + let level = Level.from_raw ctxt level in + Stake_distribution.slot_owner ctxt level slot in - let*? ctxt = Dal_apply.apply_attestation ctxt consensus_key op in return ( ctxt, Single_result diff --git a/src/proto_alpha/lib_protocol/dal_apply.ml b/src/proto_alpha/lib_protocol/dal_apply.ml index d636c421b068..08aa72783d70 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.ml +++ b/src/proto_alpha/lib_protocol/dal_apply.ml @@ -120,10 +120,9 @@ let validate_dal_attestation ctxt get_consensus_key_and_round_opt op = in return consensus_key -let apply_attestation ctxt consensus_key op = +let apply_attestation ctxt consensus_key level attestation = let open Result_syntax in let* () = assert_dal_feature_enabled ctxt in - let Dal.Attestation.{attestation; level; _} = op in let attester = pkh_of_consensus_key consensus_key in match Dal.Attestation.shards_of_attester ctxt ~attester with | None -> diff --git a/src/proto_alpha/lib_protocol/dal_apply.mli b/src/proto_alpha/lib_protocol/dal_apply.mli index 2a8cbaca6caf..7ea682789ed9 100644 --- a/src/proto_alpha/lib_protocol/dal_apply.mli +++ b/src/proto_alpha/lib_protocol/dal_apply.mli @@ -60,10 +60,11 @@ val validate_dal_attestation : Dal.Attestation.operation -> Consensus_key.pk tzresult Lwt.t -(** [apply_attestation ctxt consensus_key op] applies [op.attestation] into the - [ctxt] assuming [consensus_key.delegate] issued those attestations. *) +(** [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 -> Dal.Attestation.operation -> t tzresult + t -> Consensus_key.pk -> Raw_level.t -> Dal.Attestation.t -> t tzresult (** [validate_publish_slot_header ctxt slot] ensures that [slot_header] is valid and prevents an operation containing [slot_header] to be -- GitLab From 1cdb203d986ac5ea6e48989b5d8a0e68908b801b Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Mon, 22 Jan 2024 10:22:25 +0100 Subject: [PATCH 06/17] Alpha/DAL: rename field name for clarity --- src/proto_alpha/lib_protocol/operation_repr.ml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index 674fea38cf61..6ca00e6c175e 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -2317,7 +2317,7 @@ type preattestation_infos = {round : round_infos; slot : int} type attestation_infos = { round_infos : round_infos; slot : int; - number_of_attested_slots : int; + number_of_dal_attested_slots : int; } (** [dal_attestation_infos] gives the weight of a DAL attestation. *) @@ -2370,7 +2370,7 @@ let attestation_infos_from_content (c : consensus_content) { round_infos; slot; - number_of_attested_slots = + number_of_dal_attested_slots = Option.fold ~none:0 ~some:(fun d -> @@ -2390,7 +2390,7 @@ let dal_attestation_infos_from_dal_operation { round_infos; slot = Slot_repr.to_int slot; - number_of_attested_slots = + number_of_dal_attested_slots = Dal_attestation_repr.number_of_attested_slots attestation; } @@ -2664,8 +2664,8 @@ let compare_baking_infos infos1 infos2 = smaller the better. When the slots are also equal they are compared according to the number of attested DAL slots: the more the better. *) let compare_attestation_infos - {round_infos = infos1; slot = slot1; number_of_attested_slots = n1} - {round_infos = infos2; slot = slot2; number_of_attested_slots = n2} = + {round_infos = infos1; slot = slot1; number_of_dal_attested_slots = n1} + {round_infos = infos2; slot = slot2; number_of_dal_attested_slots = n2} = compare_pair_in_lexico_order ~cmp_fst: (compare_pair_in_lexico_order -- GitLab From 91820bb6cd0c0dd801f559155f42bcdb458667db Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Mon, 22 Jan 2024 10:41:45 +0100 Subject: [PATCH 07/17] Alpha/DAL: add comment on the DAL attestation bitset encoding --- src/proto_alpha/lib_protocol/dal_attestation_repr.mli | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/proto_alpha/lib_protocol/dal_attestation_repr.mli b/src/proto_alpha/lib_protocol/dal_attestation_repr.mli index 3be993f8829d..a7c7b0a945bb 100644 --- a/src/proto_alpha/lib_protocol/dal_attestation_repr.mli +++ b/src/proto_alpha/lib_protocol/dal_attestation_repr.mli @@ -65,6 +65,9 @@ type operation = { attester's first consensus slot at [level]. *) } +(** The size of the encoding is not bounded. However, the size of a DAL + attestation bitset is checked during validation of an attestation; and there + is a bound on the size of a generic operation. *) val encoding : t Data_encoding.t (** [empty] returns an empty [slot_attestation] which commits that -- GitLab From 9d66f3d6394622a6a401d45a4c65c28ab37541b2 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Fri, 22 Dec 2023 10:09:54 +0100 Subject: [PATCH 08/17] Alpha/Baker: enable protocol logging --- src/proto_alpha/lib_delegate/client_daemon.ml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/proto_alpha/lib_delegate/client_daemon.ml b/src/proto_alpha/lib_delegate/client_daemon.ml index 3b7cee81da8e..bca409a59e1c 100644 --- a/src/proto_alpha/lib_delegate/client_daemon.ml +++ b/src/proto_alpha/lib_delegate/client_daemon.ml @@ -139,6 +139,8 @@ module Baker = struct let* dal_config = Node_rpc.fetch_dal_config cctxt in Cryptobox.Config.init_dal ~find_srs_files dal_config in + let consumer = Protocol_logging.make_log_message_consumer () in + Lifted_protocol.set_log_message_consumer consumer ; Baking_scheduling.run cctxt ~canceler ~chain ~constants config delegates in let* () = -- GitLab From d92e77beda3f73d9c598f90924abd7ea7368444d Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Wed, 10 Jan 2024 16:49:06 +0100 Subject: [PATCH 09/17] Alpha/Baker: remove ref to closed issue --- src/proto_alpha/lib_delegate/baking_actions.ml | 2 -- src/proto_alpha/lib_delegate/state_transitions.ml | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 9f4388dbf4bd..5ba5a26e2290 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -964,8 +964,6 @@ let rec perform_action ~state_recorder state (action : action) = let*! () = start_waiting_for_attestation_quorum state in (* TODO: https://gitlab.com/tezos/tezos/-/issues/4667 Also inject attestations for the migration block. *) - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4671 - Don't inject multiple attestations? *) let* () = get_and_inject_dal_attestations state in return state | Update_to_level level_update -> diff --git a/src/proto_alpha/lib_delegate/state_transitions.ml b/src/proto_alpha/lib_delegate/state_transitions.ml index b3ba7b586e92..9e087581ea25 100644 --- a/src/proto_alpha/lib_delegate/state_transitions.ml +++ b/src/proto_alpha/lib_delegate/state_transitions.ml @@ -559,8 +559,6 @@ let propose_block_action state delegate round ~last_proposal = let attestations_in_last_proposal = last_proposal.block.quorum in (* Also insert the DAL attestations from the proposal, because the mempool may not contain them anymore *) - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4671 - The block may therefore contain multiple attestations for the same delegate. *) let dal_attestations_in_last_proposal = last_proposal.block.dal_attestations in -- GitLab From 49cc55b6f1fd8dd6657ce674082a6b6429f1fb3a Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Wed, 10 Jan 2024 16:51:44 +0100 Subject: [PATCH 10/17] Alpha/Baker: rename variables and a function --- .../lib_delegate/baking_actions.ml | 22 +++++++++---------- .../lib_delegate/baking_actions.mli | 2 +- src/proto_alpha/lib_delegate/baking_lib.ml | 4 ++-- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 5ba5a26e2290..ce2b0cd87c7d 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -436,7 +436,7 @@ let inject_block ~updated_state state signed_block = in return updated_state -let sign_consensus_votes state operations kind = +let sign_consensus_votes state votes kind = let open Lwt_result_syntax in let cctxt = state.global_state.cctxt in let chain_id = state.global_state.chain_id in @@ -447,7 +447,7 @@ let sign_consensus_votes state operations kind = Baking_files.resolve_location ~chain_id `Highwatermarks in (* Hypothesis: all consensus votes have the same round and level *) - match operations with + match votes with | [] -> return_nil | (_, (consensus_content : consensus_content)) :: _ -> let level = Raw_level.to_int32 consensus_content.level in @@ -461,7 +461,7 @@ let sign_consensus_votes state operations kind = | `Preattestation -> Baking_highwatermarks.may_sign_preattestation | `Attestation -> Baking_highwatermarks.may_sign_attestation in - let*! authorized_operations = + let*! authorized_votes = List.filter_s (fun (((consensus_key, _delegate_pkh) as delegate), _) -> let may_sign = @@ -496,14 +496,12 @@ let sign_consensus_votes state operations kind = ] )) in Lwt.return_false) - operations + votes in (* Record all consensus votes new highwatermarks as one batch *) let* () = let delegates = - List.map - (fun ((ck, _), _) -> ck.public_key_hash) - authorized_operations + List.map (fun ((ck, _), _) -> ck.public_key_hash) authorized_votes in let record_all_consensus_vote = match kind with @@ -519,7 +517,7 @@ let sign_consensus_votes state operations kind = ~level ~round in - return authorized_operations + return authorized_votes in let forge_and_sign_consensus_vote : type a. _ -> a contents_list -> _ = fun ((consensus_key, _) as delegate) contents -> @@ -586,11 +584,11 @@ let sign_consensus_votes state operations kind = (Single (Preattestation consensus_content))) authorized_consensus_votes -let inject_consensus_vote state preattestations kind = +let inject_consensus_votes state votes kind = let open Lwt_result_syntax in let cctxt = state.global_state.cctxt in let chain_id = state.global_state.chain_id in - let* signed_operations = sign_consensus_votes state preattestations kind in + let* signed_operations = sign_consensus_votes state votes kind in (* TODO: add a RPC to inject multiple operations *) let fail_inject_event, injected_event = match kind with @@ -954,11 +952,11 @@ let rec perform_action ~state_recorder state (action : action) = in updated_state | Inject_preattestations {preattestations} -> - let* () = inject_consensus_vote state preattestations `Preattestation in + let* () = inject_consensus_votes state preattestations `Preattestation in perform_action ~state_recorder state Watch_proposal | Inject_attestations {attestations} -> let* () = state_recorder ~new_state:state in - let* () = inject_consensus_vote state attestations `Attestation in + let* () = inject_consensus_votes state attestations `Attestation in (* We wait for attestations to trigger the [Quorum_reached] event *) let*! () = start_waiting_for_attestation_quorum state in diff --git a/src/proto_alpha/lib_delegate/baking_actions.mli b/src/proto_alpha/lib_delegate/baking_actions.mli index ef3cb13cfc5a..c5c35e0b8709 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.mli +++ b/src/proto_alpha/lib_delegate/baking_actions.mli @@ -104,7 +104,7 @@ val sign_consensus_votes : tzresult Lwt.t -val inject_consensus_vote : +val inject_consensus_votes : state -> (consensus_key_and_delegate * consensus_content) list -> [`Preattestation | `Attestation] -> diff --git a/src/proto_alpha/lib_delegate/baking_lib.ml b/src/proto_alpha/lib_delegate/baking_lib.ml index a04de01a2f89..a37fb1eebc38 100644 --- a/src/proto_alpha/lib_delegate/baking_lib.ml +++ b/src/proto_alpha/lib_delegate/baking_lib.ml @@ -90,7 +90,7 @@ let preattest (cctxt : Protocol_client_context.full) ?(force = false) delegates Baking_state.pp_consensus_key_and_delegate) (List.map fst consensus_list) in - Baking_actions.inject_consensus_vote state consensus_list `Preattestation + Baking_actions.inject_consensus_votes state consensus_list `Preattestation let attest (cctxt : Protocol_client_context.full) ?(force = false) delegates = let open State_transitions in @@ -127,7 +127,7 @@ let attest (cctxt : Protocol_client_context.full) ?(force = false) delegates = let* () = Baking_state.may_record_new_state ~previous_state:state ~new_state:state in - Baking_actions.inject_consensus_vote state consensus_list `Attestation + Baking_actions.inject_consensus_votes state consensus_list `Attestation let bake_at_next_level state = let open Lwt_result_syntax in -- GitLab From dc7f49800178c514460369d3cf21443d7a03e7cb Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 11 Jan 2024 12:48:46 +0100 Subject: [PATCH 11/17] Alpha/Baker: refactor sign_consensus_votes --- .../lib_delegate/baking_actions.ml | 253 +++++++++--------- 1 file changed, 124 insertions(+), 129 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index ce2b0cd87c7d..148bb94e1fc2 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -436,7 +436,7 @@ let inject_block ~updated_state state signed_block = in return updated_state -let sign_consensus_votes state votes kind = +let sign_consensus_votes_aux state votes kind ~level ~round = let open Lwt_result_syntax in let cctxt = state.global_state.cctxt in let chain_id = state.global_state.chain_id in @@ -446,143 +446,138 @@ let sign_consensus_votes state votes kind = let block_location = Baking_files.resolve_location ~chain_id `Highwatermarks in - (* Hypothesis: all consensus votes have the same round and level *) - match votes with - | [] -> return_nil - | (_, (consensus_content : consensus_content)) :: _ -> - let level = Raw_level.to_int32 consensus_content.level in - let round = consensus_content.round in - (* Filter all operations that don't satisfy the highwatermark *) - let* authorized_consensus_votes = - cctxt#with_lock @@ fun () -> - let* highwatermarks = Baking_highwatermarks.load cctxt block_location in - let may_sign_consensus_vote = - match kind with - | `Preattestation -> Baking_highwatermarks.may_sign_preattestation - | `Attestation -> Baking_highwatermarks.may_sign_attestation - in - let*! authorized_votes = - List.filter_s - (fun (((consensus_key, _delegate_pkh) as delegate), _) -> - let may_sign = - may_sign_consensus_vote - highwatermarks - ~delegate:consensus_key.public_key_hash - ~level - ~round - in - if may_sign || state.global_state.config.force then - Lwt.return_true - else - let*! () = - match kind with - | `Preattestation -> - Events.( - emit - skipping_preattestation - ( delegate, - [ - Baking_highwatermarks.Block_previously_preattested - {round; level}; - ] )) - | `Attestation -> - Events.( - emit - skipping_attestation - ( delegate, - [ - Baking_highwatermarks.Block_previously_attested - {round; level}; - ] )) - in - Lwt.return_false) - votes - in - (* Record all consensus votes new highwatermarks as one batch *) - let* () = - let delegates = - List.map (fun ((ck, _), _) -> ck.public_key_hash) authorized_votes - in - let record_all_consensus_vote = - match kind with - | `Preattestation -> - Baking_highwatermarks.record_all_preattestations - | `Attestation -> Baking_highwatermarks.record_all_attestations + (* Filter all operations that don't satisfy the highwatermark *) + let* authorized_consensus_votes = + cctxt#with_lock @@ fun () -> + let* highwatermarks = Baking_highwatermarks.load cctxt block_location in + let may_sign_consensus_vote = + match kind with + | `Preattestation -> Baking_highwatermarks.may_sign_preattestation + | `Attestation -> Baking_highwatermarks.may_sign_attestation + in + let*! authorized_votes = + List.filter_s + (fun (((consensus_key, _delegate_pkh) as delegate), _) -> + let may_sign = + may_sign_consensus_vote + highwatermarks + ~delegate:consensus_key.public_key_hash + ~level + ~round in - record_all_consensus_vote - highwatermarks - cctxt - block_location - ~delegates - ~level - ~round - in - return authorized_votes - in - let forge_and_sign_consensus_vote : type a. _ -> a contents_list -> _ = - fun ((consensus_key, _) as delegate) contents -> - let shell = - (* The branch is the latest finalized block. *) - { - Tezos_base.Operation.branch = - state.level_state.latest_proposal.predecessor.shell.predecessor; - } - in - let watermark = - match kind with - | `Preattestation -> - Operation.(to_watermark (Preattestation chain_id)) - | `Attestation -> Operation.(to_watermark (Attestation chain_id)) - in - let unsigned_operation = (shell, Contents_list contents) in - let unsigned_operation_bytes = - Data_encoding.Binary.to_bytes_exn - Operation.unsigned_encoding - unsigned_operation - in - let level = Raw_level.to_int32 consensus_content.level in - let round = consensus_content.round in - let sk_uri = consensus_key.secret_key_uri in - let*! signature = - Client_keys.sign cctxt ~watermark sk_uri unsigned_operation_bytes - in - match signature with - | Error err -> + if may_sign || state.global_state.config.force then Lwt.return_true + else let*! () = match kind with | `Preattestation -> - Events.(emit skipping_preattestation (delegate, err)) + Events.( + emit + skipping_preattestation + ( delegate, + [ + Baking_highwatermarks.Block_previously_preattested + {round; level}; + ] )) | `Attestation -> - Events.(emit skipping_attestation (delegate, err)) - in - return_none - | Ok signature -> - let protocol_data = - Operation_data {contents; signature = Some signature} + Events.( + emit + skipping_attestation + ( delegate, + [ + Baking_highwatermarks.Block_previously_attested + {round; level}; + ] )) in - let operation : Operation.packed = {shell; protocol_data} in - return_some (delegate, operation, level, round) + Lwt.return_false) + votes + in + (* Record all consensus votes new highwatermarks as one batch *) + let* () = + let delegates = + List.map (fun ((ck, _), _) -> ck.public_key_hash) authorized_votes in - List.filter_map_es - (fun (delegate, consensus_content) -> - let event = - match kind with - | `Preattestation -> Events.signing_preattestation - | `Attestation -> Events.signing_attestation - in - let*! () = Events.(emit event delegate) in + let record_all_consensus_vote = + match kind with + | `Preattestation -> Baking_highwatermarks.record_all_preattestations + | `Attestation -> Baking_highwatermarks.record_all_attestations + in + record_all_consensus_vote + highwatermarks + cctxt + block_location + ~delegates + ~level + ~round + in + return authorized_votes + in + let forge_and_sign_consensus_vote : type a. _ -> a contents_list -> _ = + fun ((consensus_key, _) as delegate) contents -> + let shell = + (* The branch is the latest finalized block. *) + { + Tezos_base.Operation.branch = + state.level_state.latest_proposal.predecessor.shell.predecessor; + } + in + let watermark = + match kind with + | `Preattestation -> Operation.(to_watermark (Preattestation chain_id)) + | `Attestation -> Operation.(to_watermark (Attestation chain_id)) + in + let unsigned_operation = (shell, Contents_list contents) in + let unsigned_operation_bytes = + Data_encoding.Binary.to_bytes_exn + Operation.unsigned_encoding + unsigned_operation + in + let sk_uri = consensus_key.secret_key_uri in + let*! signature = + Client_keys.sign cctxt ~watermark sk_uri unsigned_operation_bytes + in + match signature with + | Error err -> + let*! () = match kind with - | `Attestation -> - forge_and_sign_consensus_vote - delegate - (Single - (Attestation - {consensus_content; dal_content = None (* TODO *)})) | `Preattestation -> - forge_and_sign_consensus_vote - delegate - (Single (Preattestation consensus_content))) - authorized_consensus_votes + Events.(emit skipping_preattestation (delegate, err)) + | `Attestation -> Events.(emit skipping_attestation (delegate, err)) + in + return_none + | Ok signature -> + let protocol_data = + Operation_data {contents; signature = Some signature} + in + let operation : Operation.packed = {shell; protocol_data} in + return_some (delegate, operation, level, round) + in + List.filter_map_es + (fun (delegate, consensus_content) -> + let event = + match kind with + | `Preattestation -> Events.signing_preattestation + | `Attestation -> Events.signing_attestation + in + let*! () = Events.(emit event delegate) in + match kind with + | `Attestation -> + forge_and_sign_consensus_vote + delegate + (Single + (Attestation {consensus_content; dal_content = None (* TODO *)})) + | `Preattestation -> + forge_and_sign_consensus_vote + delegate + (Single (Preattestation consensus_content))) + authorized_consensus_votes + +let sign_consensus_votes state votes kind = + (* Hypothesis: all consensus votes have the same round and level *) + match votes with + | [] -> return_nil + | (_, ({level; round; _} : consensus_content)) :: _ -> + let level = Raw_level.to_int32 level in + sign_consensus_votes_aux state votes kind ~level ~round let inject_consensus_votes state votes kind = let open Lwt_result_syntax in -- GitLab From 4b1a96d864bb0cbc81297b80d83073f087c1d28f Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 11 Jan 2024 12:59:55 +0100 Subject: [PATCH 12/17] Alpha/Baker: put DAL attestations in consensus attestations --- .../lib_delegate/baking_actions.ml | 255 +++++------------- .../lib_delegate/baking_actions.mli | 16 -- src/proto_alpha/lib_delegate/baking_events.ml | 42 +-- src/proto_alpha/lib_delegate/baking_lib.ml | 11 - .../lib_delegate/operation_worker.ml | 8 +- 5 files changed, 77 insertions(+), 255 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 148bb94e1fc2..2a6fce7a641a 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -436,6 +436,27 @@ let inject_block ~updated_state state signed_block = in return updated_state +let only_if_dal_feature_enabled = + let no_dal_node_warning_counter = ref 0 in + fun state ~default_value f -> + let open Lwt_result_syntax in + let open Constants in + let Parametric.{dal = {feature_enable; _}; _} = + state.global_state.constants.parametric + in + if feature_enable then + match state.global_state.dal_node_rpc_ctxt with + | None -> + incr no_dal_node_warning_counter ; + let*! () = + if !no_dal_node_warning_counter mod 10 = 1 then + Events.(emit no_dal_node ()) + else Lwt.return_unit + in + return default_value + | Some ctxt -> f ctxt + else return default_value + let sign_consensus_votes_aux state votes kind ~level ~round = let open Lwt_result_syntax in let cctxt = state.global_state.cctxt in @@ -551,6 +572,48 @@ let sign_consensus_votes_aux state votes kind ~level ~round = let operation : Operation.packed = {shell; protocol_data} in return_some (delegate, operation, level, round) in + let get_dal_content delegate = + only_if_dal_feature_enabled + state + ~default_value:None + (fun dal_node_rpc_ctxt -> + let*! tz_res = + Node_rpc.get_attestable_slots + dal_node_rpc_ctxt + (fst delegate).public_key_hash + ~attested_level:(Int32.succ level) + in + match tz_res with + | Error errs -> + let*! () = + Events.(emit failed_to_get_dal_attestations (delegate, errs)) + in + return_none + | Ok res -> ( + match res with + | Tezos_dal_node_services.Types.Not_in_committee -> return_none + | Attestable_slots {slots = attestation_flags; published_level} -> + let number_of_slots = + state.global_state.constants.parametric.dal.number_of_slots + in + let dal_attestation = + List.fold_left_i + (fun i acc flag -> + match Dal.Slot_index.of_int_opt ~number_of_slots i with + | Some index when flag -> Dal.Attestation.commit acc index + | None | Some _ -> acc) + Dal.Attestation.empty + attestation_flags + in + let*! () = + let bitset_int = Bitset.to_z (dal_attestation :> Bitset.t) in + Events.( + emit + attach_dal_attestation + (delegate, bitset_int, published_level, level, round)) + in + return_some {attestation = dal_attestation})) + in List.filter_map_es (fun (delegate, consensus_content) -> let event = @@ -561,10 +624,10 @@ let sign_consensus_votes_aux state votes kind ~level ~round = let*! () = Events.(emit event delegate) in match kind with | `Attestation -> + let* dal_content = get_dal_content delegate in forge_and_sign_consensus_vote delegate - (Single - (Attestation {consensus_content; dal_content = None (* TODO *)})) + (Single (Attestation {consensus_content; dal_content})) | `Preattestation -> forge_and_sign_consensus_vote delegate @@ -608,191 +671,6 @@ let inject_consensus_votes state votes kind = return_unit)) signed_operations -let sign_dal_attestations state attestations = - let open Lwt_result_syntax in - let cctxt = state.global_state.cctxt in - let chain_id = state.global_state.chain_id in - (* N.b. signing a lot of operations may take some time *) - (* Don't parallelize signatures: the signer might not be able to - handle concurrent requests *) - let shell = - { - Tezos_base.Operation.branch = - state.level_state.latest_proposal.predecessor.hash; - } - in - List.filter_map_es - (fun (((consensus_key, _) as delegate), operation_content, published_level) -> - let watermark = Operation.(to_watermark (Dal_attestation chain_id)) in - let contents = Single (Dal_attestation operation_content) in - let unsigned_operation = (shell, Contents_list contents) in - let unsigned_operation_bytes = - Data_encoding.Binary.to_bytes_exn - Operation.unsigned_encoding_with_legacy_attestation_name - unsigned_operation - in - let*! signature = - Client_keys.sign - cctxt - ~watermark - consensus_key.secret_key_uri - unsigned_operation_bytes - in - match signature with - | Error err -> - let*! () = Events.(emit skipping_dal_attestation (delegate, err)) in - return_none - | Ok signature -> - let protocol_data = - Operation_data {contents; signature = Some signature} - in - let packed_operation : Operation.packed = {shell; protocol_data} in - return_some - (delegate, packed_operation, operation_content, published_level)) - attestations - -let inject_dal_attestations state attestations = - let open Lwt_result_syntax in - let cctxt = state.global_state.cctxt in - let chain_id = state.global_state.chain_id in - let* signed_operations = sign_dal_attestations state attestations in - List.iter_ep - (fun (delegate, signed_operation, op_content, published_level) -> - let encoded_op = - Data_encoding.Binary.to_bytes_exn - Operation.encoding_with_legacy_attestation_name - signed_operation - in - let* oph = - Shell_services.Injection.operation - cctxt - ~chain:(`Hash chain_id) - encoded_op - in - let bitset_int = - Bitset.to_z (op_content.Dal.Attestation.attestation :> Bitset.t) - in - let*! () = - Events.( - emit - dal_attestation_injected - ( oph, - delegate, - bitset_int, - published_level, - op_content.level, - op_content.round )) - in - return_unit) - signed_operations - -let no_dal_node_warning_counter = ref 0 - -let only_if_dal_feature_enabled state ~default_value f = - let open Lwt_result_syntax in - let open Constants in - let Parametric.{dal = {feature_enable; _}; _} = - state.global_state.constants.parametric - in - if feature_enable then - match state.global_state.dal_node_rpc_ctxt with - | None -> - incr no_dal_node_warning_counter ; - let*! () = - if !no_dal_node_warning_counter mod 10 = 1 then - Events.(emit no_dal_node ()) - else Lwt.return_unit - in - return default_value - | Some ctxt -> f ctxt - else return default_value - -let get_dal_attestations state = - let open Lwt_result_syntax in - only_if_dal_feature_enabled state ~default_value:[] (fun dal_node_rpc_ctxt -> - let attestation_level = state.level_state.current_level in - let attested_level = Int32.succ attestation_level in - let delegates = - List.map - (fun delegate_slot -> - (delegate_slot.consensus_key_and_delegate, delegate_slot.first_slot)) - (Delegate_slots.own_delegates state.level_state.delegate_slots) - in - let signing_key delegate = (fst delegate).public_key_hash in - let* attestations = - List.fold_left_es - (fun acc (delegate, first_slot) -> - let*! tz_res = - Node_rpc.get_attestable_slots - dal_node_rpc_ctxt - (signing_key delegate) - ~attested_level - in - match tz_res with - | Error errs -> - let*! () = - Events.(emit failed_to_get_dal_attestations (delegate, errs)) - in - return acc - | Ok res -> ( - match res with - | Tezos_dal_node_services.Types.Not_in_committee -> return acc - | Attestable_slots {slots = attestation; published_level} -> - if List.exists Fun.id attestation then - return - (( delegate, - attestation, - published_level, - state.round_state.current_round, - first_slot ) - :: acc) - else - (* No slot is attested, no need to send an attestation, at least - for now. *) - let*! () = - Events.( - emit - dal_attestation_void - ( delegate, - attestation_level, - state.round_state.current_round, - published_level )) - in - return acc)) - [] - delegates - in - let number_of_slots = - state.global_state.constants.parametric.dal.number_of_slots - in - List.map - (fun (delegate, attestation_flags, published_level, round, first_slot) -> - let attestation = - List.fold_left_i - (fun i acc flag -> - match Dal.Slot_index.of_int_opt ~number_of_slots i with - | Some index when flag -> Dal.Attestation.commit acc index - | None | Some _ -> acc) - Dal.Attestation.empty - attestation_flags - in - ( delegate, - Dal.Attestation. - { - attestation; - level = Raw_level.of_int32_exn attestation_level; - round; - slot = first_slot; - }, - published_level )) - attestations - |> return) - -let get_and_inject_dal_attestations state = - let open Lwt_result_syntax in - let* attestations = get_dal_attestations state in - inject_dal_attestations state attestations - let prepare_waiting_for_quorum state = let consensus_threshold = state.global_state.constants.parametric.consensus_threshold @@ -955,9 +833,6 @@ let rec perform_action ~state_recorder state (action : action) = (* We wait for attestations to trigger the [Quorum_reached] event *) let*! () = start_waiting_for_attestation_quorum state in - (* TODO: https://gitlab.com/tezos/tezos/-/issues/4667 - Also inject attestations for the migration block. *) - let* () = get_and_inject_dal_attestations state in return state | Update_to_level level_update -> let* new_state, new_action = update_to_level state level_update in diff --git a/src/proto_alpha/lib_delegate/baking_actions.mli b/src/proto_alpha/lib_delegate/baking_actions.mli index c5c35e0b8709..c68747743ed0 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.mli +++ b/src/proto_alpha/lib_delegate/baking_actions.mli @@ -110,22 +110,6 @@ val inject_consensus_votes : [`Preattestation | `Attestation] -> unit tzresult Lwt.t -val sign_dal_attestations : - state -> - (consensus_key_and_delegate * Dal.Attestation.operation * int32) list -> - (consensus_key_and_delegate - * packed_operation - * Dal.Attestation.operation - * int32) - list - tzresult - Lwt.t - -val get_dal_attestations : - state -> - (consensus_key_and_delegate * Dal.Attestation.operation * int32) list tzresult - Lwt.t - val prepare_waiting_for_quorum : state -> int * (slot:Slot.t -> int option) * Operation_worker.candidate diff --git a/src/proto_alpha/lib_delegate/baking_events.ml b/src/proto_alpha/lib_delegate/baking_events.ml index ca3905db37a6..54ec36f67c3e 100644 --- a/src/proto_alpha/lib_delegate/baking_events.ml +++ b/src/proto_alpha/lib_delegate/baking_events.ml @@ -612,17 +612,6 @@ module Actions = struct ~pp2:Error_monad.pp_print_trace ("trace", Error_monad.trace_encoding) - let skipping_dal_attestation = - declare_2 - ~section - ~name:"skipping_dal_attestation" - ~level:Error - ~msg:"unable to sign DAL attestation for {delegate} -- {trace}" - ~pp1:Baking_state.pp_consensus_key_and_delegate - ("delegate", Baking_state.consensus_key_and_delegate_encoding) - ~pp2:Error_monad.pp_print_trace - ("trace", Error_monad.trace_encoding) - let failed_to_inject_preattestation = declare_2 ~section @@ -690,39 +679,22 @@ module Actions = struct ~pp4:Round.pp ("round", Round.encoding) - let dal_attestation_injected = - declare_6 + let attach_dal_attestation = + declare_5 ~section - ~name:"dal_attestation_injected" + ~name:"attach_dal_attestation" ~level:Notice ~msg: - "injected DAL attestation {ophash} for level {attestation_level}, \ - round {round}, with bitset {bitset} for {delegate} to attest slots \ + "ready to attach DAL attestation for level {attestation_level}, round \ + {round}, with bitset {bitset} for {delegate} to attest slots \ published at level {published_level}" - ~pp1:Operation_hash.pp - ("ophash", Operation_hash.encoding) - ~pp2:Baking_state.pp_consensus_key_and_delegate + ~pp1:Baking_state.pp_consensus_key_and_delegate ("delegate", Baking_state.consensus_key_and_delegate_encoding) - ~pp3:Z.pp_print + ~pp2:Z.pp_print ("bitset", Data_encoding.n) ("published_level", Data_encoding.int32) - ("attestation_level", Raw_level.encoding) - ("round", Round.encoding) - - let dal_attestation_void = - declare_4 - ~section - ~name:"dal_attestation_void" - ~level:Notice - ~msg: - "Skipping the injection of the DAL attestation for attestation level \ - {attestation_level}, round {round}, as currently no slot published at \ - level {published_level} is attestable." - ~pp1:Baking_state.pp_consensus_key_and_delegate - ("delegate", Baking_state.consensus_key_and_delegate_encoding) ("attestation_level", Data_encoding.int32) ("round", Round.encoding) - ("published_level", Data_encoding.int32) let synchronizing_round = declare_1 diff --git a/src/proto_alpha/lib_delegate/baking_lib.ml b/src/proto_alpha/lib_delegate/baking_lib.ml index a37fb1eebc38..3404597e6883 100644 --- a/src/proto_alpha/lib_delegate/baking_lib.ml +++ b/src/proto_alpha/lib_delegate/baking_lib.ml @@ -553,17 +553,6 @@ let rec baking_minimal_timestamp ~count state current_mempool (List.map (fun (_, x, _, _) -> x) signed_attestations) in - let* own_dal_attestations = Baking_actions.get_dal_attestations state in - let* signed_dal_attestations = - Baking_actions.sign_dal_attestations state own_dal_attestations - in - let pool = - Operation_pool.add_operations - pool - (List.map - (fun (_delegate, op, _bitset, _published_level) -> op) - signed_dal_attestations) - in let kind = Baking_actions.Fresh pool in let block_to_bake : Baking_actions.block_to_bake = { diff --git a/src/proto_alpha/lib_delegate/operation_worker.ml b/src/proto_alpha/lib_delegate/operation_worker.ml index 3a591333e6b3..42d91d24e545 100644 --- a/src/proto_alpha/lib_delegate/operation_worker.ml +++ b/src/proto_alpha/lib_delegate/operation_worker.ml @@ -185,9 +185,7 @@ module Attestation_set = Set.Make (struct protocol_data = { contents = - Single - (Attestation - {consensus_content = op1; dal_content = _ (* TODO *)}); + Single (Attestation {consensus_content = op1; dal_content = _}); _; }; shell = _; @@ -203,6 +201,10 @@ module Attestation_set = Set.Make (struct shell = _; } : t) = + (* We do not consider the DAL content (therefore two attestations with the + same consensus content but different DAL content are considered equal), + in order to correctly count the voting power. Note however that there + should be no such operations in the mempool in the first place. *) compare_consensus_contents op1 op2 end) -- GitLab From 9ca64b8603ee01f848aa1e7bd572a5421ebd4c70 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 11 Jan 2024 14:45:42 +0100 Subject: [PATCH 13/17] Alpha/Baker: ignore DAL attestation operations --- src/proto_alpha/lib_delegate/baking_state.ml | 16 +------ src/proto_alpha/lib_delegate/baking_state.mli | 1 - src/proto_alpha/lib_delegate/node_rpc.ml | 15 ++---- .../lib_delegate/operation_pool.ml | 30 +++--------- .../lib_delegate/operation_pool.mli | 4 -- .../lib_delegate/state_transitions.ml | 48 +++++-------------- 6 files changed, 24 insertions(+), 90 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_state.ml b/src/proto_alpha/lib_delegate/baking_state.ml index 0c5286212d12..7ac47ce40ef5 100644 --- a/src/proto_alpha/lib_delegate/baking_state.ml +++ b/src/proto_alpha/lib_delegate/baking_state.ml @@ -108,7 +108,6 @@ type block_info = { round : Round.t; prequorum : prequorum option; quorum : Kind.attestation operation list; - dal_attestations : Kind.dal_attestation operation list; payload : Operation_pool.payload; } @@ -172,7 +171,6 @@ let block_info_encoding = round; prequorum; quorum; - dal_attestations; payload; } -> ( hash, @@ -182,7 +180,6 @@ let block_info_encoding = round, prequorum, List.map Operation.pack quorum, - List.map Operation.pack dal_attestations, payload )) (fun ( hash, shell, @@ -191,7 +188,6 @@ let block_info_encoding = round, prequorum, quorum, - dal_attestations, payload ) -> { hash; @@ -201,11 +197,9 @@ let block_info_encoding = round; prequorum; quorum = List.filter_map Operation_pool.unpack_attestation quorum; - dal_attestations = - List.filter_map Operation_pool.unpack_dal_attestation dal_attestations; payload; }) - (obj9 + (obj8 (req "hash" Block_hash.encoding) (req "shell" Block_header.shell_header_encoding) (req "payload_hash" Block_payload_hash.encoding) @@ -215,9 +209,6 @@ let block_info_encoding = (req "quorum" (list (dynamic_size Operation.encoding_with_legacy_attestation_name))) - (req - "dal_attestations" - (list (dynamic_size Operation.encoding_with_legacy_attestation_name))) (req "payload" Operation_pool.payload_encoding)) let round_of_shell_header shell_header = @@ -808,15 +799,13 @@ let pp_block_info fmt round; prequorum; quorum; - dal_attestations; payload; payload_round; } = Format.fprintf fmt "@[Block:@ hash: %a@ payload_hash: %a@ level: %ld@ round: %a@ \ - prequorum: %a@ quorum: %d attestations@ dal_attestations: %d@ payload: \ - %a@ payload round: %a@]" + prequorum: %a@ quorum: %d attestations@ payload: %a@ payload round: %a@]" Block_hash.pp hash Block_payload_hash.pp_short @@ -827,7 +816,6 @@ let pp_block_info fmt (pp_option pp_prequorum) prequorum (List.length quorum) - (List.length dal_attestations) Operation_pool.pp_payload payload Round.pp diff --git a/src/proto_alpha/lib_delegate/baking_state.mli b/src/proto_alpha/lib_delegate/baking_state.mli index 6430886bfe42..037adb00dda4 100644 --- a/src/proto_alpha/lib_delegate/baking_state.mli +++ b/src/proto_alpha/lib_delegate/baking_state.mli @@ -65,7 +65,6 @@ type block_info = { round : Round.t; prequorum : prequorum option; quorum : Kind.attestation operation list; - dal_attestations : Kind.dal_attestation operation list; payload : Operation_pool.payload; } diff --git a/src/proto_alpha/lib_delegate/node_rpc.ml b/src/proto_alpha/lib_delegate/node_rpc.ml index ec6e4c369770..fc9608f62ef9 100644 --- a/src/proto_alpha/lib_delegate/node_rpc.ml +++ b/src/proto_alpha/lib_delegate/node_rpc.ml @@ -82,20 +82,14 @@ let info_of_header_and_ops ~in_protocol block_hash block_header operations = let* round = Environment.wrap_tzresult @@ Fitness.round_from_raw shell.fitness in - let payload_hash, payload_round, prequorum, quorum, dal_attestations, payload - = + let payload_hash, payload_round, prequorum, quorum, payload = if not in_protocol then (* The first block in the protocol is baked using the previous protocol, the encodings might change. The baker's logic is to consider final the first block of a new protocol and not attest it. Therefore, we do not need to have the correct values here. *) - ( dummy_payload_hash, - Round.zero, - None, - [], - [], - Operation_pool.empty_payload ) + (dummy_payload_hash, Round.zero, None, [], Operation_pool.empty_payload) else let payload_hash, payload_round = match @@ -107,13 +101,13 @@ let info_of_header_and_ops ~in_protocol block_hash block_header operations = (payload_hash, payload_round) | None -> assert false in - let preattestations, quorum, dal_attestations, payload = + let preattestations, quorum, payload = WithExceptions.Option.get ~loc:__LOC__ (Operation_pool.extract_operations_of_list_list operations) in let prequorum = Option.bind preattestations extract_prequorum in - (payload_hash, payload_round, prequorum, quorum, dal_attestations, payload) + (payload_hash, payload_round, prequorum, quorum, payload) in return { @@ -124,7 +118,6 @@ let info_of_header_and_ops ~in_protocol block_hash block_header operations = round; prequorum; quorum; - dal_attestations; payload; } diff --git a/src/proto_alpha/lib_delegate/operation_pool.ml b/src/proto_alpha/lib_delegate/operation_pool.ml index 91eafcf24502..42fcc2a4efd1 100644 --- a/src/proto_alpha/lib_delegate/operation_pool.ml +++ b/src/proto_alpha/lib_delegate/operation_pool.ml @@ -273,13 +273,6 @@ let unpack_attestation packed_attestation = Some ({shell; protocol_data = data} : Kind.attestation Operation.t) | _ -> None -let unpack_dal_attestation packed_dal_attestation = - let {shell; protocol_data = Operation_data data} = packed_dal_attestation in - match data with - | {contents = Single (Dal_attestation _); _} -> - Some ({shell; protocol_data = data} : Kind.dal_attestation Operation.t) - | _ -> None - let filter_preattestations ops = List.filter_map (function @@ -337,30 +330,21 @@ let ordered_pool_of_payload ~consensus_operations let extract_operations_of_list_list = function | [consensus; votes_payload; anonymous_payload; managers_payload] -> - let preattestations, attestations, dal_attestations = + let preattestations, attestations = List.fold_left (fun ( (preattestations : Kind.preattestation Operation.t list), - (attestations : Kind.attestation Operation.t list), - (dal_attestations : Kind.dal_attestation Operation.t list) ) + (attestations : Kind.attestation Operation.t 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, - dal_attestations ) + ({shell; protocol_data = data} :: preattestations, attestations) | {contents = Single (Attestation _); _} -> - ( preattestations, - {shell; protocol_data = data} :: attestations, - dal_attestations ) - | {contents = Single (Dal_attestation _); _} -> - ( preattestations, - attestations, - {shell; protocol_data = data} :: dal_attestations ) + (preattestations, {shell; protocol_data = data} :: attestations) | _ -> (* unreachable *) - (preattestations, attestations, dal_attestations)) - ([], [], []) + (preattestations, attestations)) + ([], []) consensus (* N.b. the order doesn't matter *) in @@ -368,7 +352,7 @@ let extract_operations_of_list_list = function if preattestations = [] then None else Some preattestations in let payload = {votes_payload; anonymous_payload; managers_payload} in - Some (preattestations, attestations, dal_attestations, payload) + Some (preattestations, attestations, payload) | _ -> None let filter_pool p {consensus; votes; anonymous; managers} = diff --git a/src/proto_alpha/lib_delegate/operation_pool.mli b/src/proto_alpha/lib_delegate/operation_pool.mli index f9bf1f0c63d6..a7159f557254 100644 --- a/src/proto_alpha/lib_delegate/operation_pool.mli +++ b/src/proto_alpha/lib_delegate/operation_pool.mli @@ -97,9 +97,6 @@ val unpack_preattestation : val unpack_attestation : packed_operation -> Kind.attestation operation option -val unpack_dal_attestation : - packed_operation -> Kind.dal_attestation operation option - val filter_preattestations : packed_operation list -> Kind.preattestation operation list @@ -115,7 +112,6 @@ val extract_operations_of_list_list : packed_operation list list -> (Kind.preattestation operation list option * Kind.attestation operation list - * Kind.dal_attestation operation list * payload) option diff --git a/src/proto_alpha/lib_delegate/state_transitions.ml b/src/proto_alpha/lib_delegate/state_transitions.ml index 9e087581ea25..4826254a5649 100644 --- a/src/proto_alpha/lib_delegate/state_transitions.ml +++ b/src/proto_alpha/lib_delegate/state_transitions.ml @@ -415,10 +415,10 @@ and may_switch_branch ~is_proposal_applied state new_proposal = let* () = Events.(emit branch_proposal_has_same_prequorum ()) in do_nothing state -(* Create a fresh block proposal containing the current operations of - the mempool in [state] and the additional [attestations] and - [dal_attestations] for [delegate] at round [round]. *) -let prepare_block_to_bake ~attestations ~dal_attestations ?last_proposal +(* Create a fresh block proposal containing the current operations of the + mempool in [state] and the additional [attestations] for [delegate] at round + [round]. *) +let prepare_block_to_bake ~attestations ?last_proposal ~(predecessor : block_info) state delegate round = (* The block to bake embeds the operations gathered by the worker. However, consensus operations that are not relevant for @@ -466,16 +466,11 @@ let prepare_block_to_bake ~attestations ~dal_attestations ?last_proposal let filtered_mempool = {current_mempool with consensus = relevant_consensus_operations} in - (* 3. Add the additional given [attestations] and [dal_attestations]. + (* 3. Add the additional given [attestations]. N.b. this is a set: there won't be duplicates *) - let pool = - Operation_pool.add_operations - filtered_mempool - (List.map Operation.pack attestations) - in Operation_pool.add_operations - pool - (List.map Operation.pack dal_attestations) + filtered_mempool + (List.map Operation.pack attestations) in let kind = Fresh operation_pool in let* () = Events.(emit preparing_fresh_block (delegate, round)) in @@ -486,13 +481,12 @@ let prepare_block_to_bake ~attestations ~dal_attestations ?last_proposal in return {predecessor; round; delegate; kind; force_apply} -let forge_fresh_block_action ~attestations ~dal_attestations ?last_proposal +let forge_fresh_block_action ~attestations ?last_proposal ~(predecessor : block_info) state delegate = let open Lwt_syntax in let* block_to_bake = prepare_block_to_bake ~attestations - ~dal_attestations ?last_proposal ~predecessor state @@ -504,7 +498,7 @@ let forge_fresh_block_action ~attestations ~dal_attestations ?last_proposal (** Create an inject action that will inject either a fresh block or the pre-emptively forged block if it exists. *) -let propose_fresh_block_action ~attestations ~dal_attestations ?last_proposal +let propose_fresh_block_action ~attestations ?last_proposal ~(predecessor : block_info) state delegate round = (* TODO check if there is a trace where we could not have updated the level *) let open Lwt_syntax in @@ -526,7 +520,6 @@ let propose_fresh_block_action ~attestations ~dal_attestations ?last_proposal let+ block_to_bake = prepare_block_to_bake ~attestations - ~dal_attestations ?last_proposal ~predecessor state @@ -557,14 +550,8 @@ let propose_block_action state delegate round ~last_proposal = payload *) assert (state.level_state.locked_round = None) ; let attestations_in_last_proposal = last_proposal.block.quorum in - (* Also insert the DAL attestations from the proposal, because the mempool - may not contain them anymore *) - let dal_attestations_in_last_proposal = - last_proposal.block.dal_attestations - in propose_fresh_block_action ~attestations:attestations_in_last_proposal - ~dal_attestations:dal_attestations_in_last_proposal state ~last_proposal:last_proposal.block ~predecessor:last_proposal.predecessor @@ -595,9 +582,8 @@ 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) - @ List.map Operation.pack proposal.block.dal_attestations) + (List.map Operation.pack proposal.block.quorum + @ List.map Operation.pack prequorum.preattestations) in let attestation_filter = { @@ -697,15 +683,9 @@ let time_to_forge_block state = assert false | Some elected_block, Some {consensus_key_and_delegate; _} -> let attestations = elected_block.attestation_qc in - let dal_attestations = - (* Unlike proposal attestations, we don't watch and store DAL attestations for - each proposal, we'll retrieve them from the mempool *) - [] - in let* action = forge_fresh_block_action ~attestations - ~dal_attestations ~predecessor:elected_block.proposal.block state consensus_key_and_delegate @@ -726,11 +706,6 @@ let time_to_bake_at_next_level state at_round = assert false | Some elected_block, Some {consensus_key_and_delegate; _} -> let attestations = elected_block.attestation_qc in - let dal_attestations = - (* Unlike proposal attestations, we don't watch and store DAL attestations for - each proposal, we'll retrieve them from the mempool *) - [] - in let new_level_state = {state.level_state with next_level_proposed_round = Some at_round} in @@ -738,7 +713,6 @@ let time_to_bake_at_next_level state at_round = let* action = propose_fresh_block_action ~attestations - ~dal_attestations ~predecessor:elected_block.proposal.block new_state consensus_key_and_delegate -- GitLab From 23fadc77a90ba929fd580fa524c727f3f103d52d Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 18 Jan 2024 11:46:48 +0100 Subject: [PATCH 14/17] Alpha/Baker: move two functions in a different module ... because otherwise later we'll get a cyclic dependency --- .../lib_delegate/baking_scheduling.ml | 58 ------------------- .../lib_delegate/baking_scheduling.mli | 2 - src/proto_alpha/lib_delegate/baking_state.ml | 56 +++++++++++++++++- src/proto_alpha/lib_delegate/baking_state.mli | 13 +++++ 4 files changed, 68 insertions(+), 61 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_scheduling.ml b/src/proto_alpha/lib_delegate/baking_scheduling.ml index 8a20dbe3919e..90b52e00db68 100644 --- a/src/proto_alpha/lib_delegate/baking_scheduling.ml +++ b/src/proto_alpha/lib_delegate/baking_scheduling.ml @@ -86,33 +86,6 @@ let find_in_known_round_intervals known_round_intervals ~predecessor_timestamp known_round_intervals {predecessor_timestamp; predecessor_round; time_interval = (now, now)}) -(** Memoization wrapper for [Round.timestamp_of_round]. *) -let timestamp_of_round state ~predecessor_timestamp ~predecessor_round ~round = - let open Result_syntax in - let open Baking_cache in - let known_timestamps = state.global_state.cache.known_timestamps in - match - Timestamp_of_round_cache.find_opt - known_timestamps - (predecessor_timestamp, predecessor_round, round) - with - (* Compute and register the timestamp if not already existing. *) - | None -> - let* ts = - Protocol.Alpha_context.Round.timestamp_of_round - state.global_state.round_durations - ~predecessor_timestamp - ~predecessor_round - ~round - in - Timestamp_of_round_cache.replace - known_timestamps - (predecessor_timestamp, predecessor_round, round) - ts ; - return ts - (* If it already exists, just fetch from the memoization table. *) - | Some ts -> return ts - let sleep_until_ptime ptime = let delay = Ptime.diff ptime (Time.System.now ()) in if Ptime.Span.compare delay Ptime.Span.zero < 0 then None @@ -273,37 +246,6 @@ let rec wait_next_event ~timeout loop_state = return_some (Quorum_reached (candidate, attestation_qc)) | `Timeout e -> return_some (Timeout e) -(** From the current [state], the function returns an optional - association pair, which consists of the next round timestamp and its - round. *) -let compute_next_round_time state = - let open Baking_state in - let proposal = - match state.level_state.attestable_payload with - | None -> state.level_state.latest_proposal - | Some {proposal; _} -> proposal - in - if Baking_state.is_first_block_in_protocol proposal then None - else - match state.level_state.next_level_proposed_round with - | Some _proposed_round -> - (* TODO? do something, if we don't, we won't be able to - repropose a block at next level. *) - None - | None -> ( - let predecessor_timestamp = proposal.predecessor.shell.timestamp in - let predecessor_round = proposal.predecessor.round in - let next_round = Round.succ state.round_state.current_round in - match - timestamp_of_round - state - ~predecessor_timestamp - ~predecessor_round - ~round:next_round - with - | Ok timestamp -> Some (timestamp, next_round) - | _ -> assert false) - let rec first_own_round_in_range delegate_slots ~committee_size ~included_min ~excluded_max = if included_min >= excluded_max then None diff --git a/src/proto_alpha/lib_delegate/baking_scheduling.mli b/src/proto_alpha/lib_delegate/baking_scheduling.mli index 9301643bef4a..44649c7af526 100644 --- a/src/proto_alpha/lib_delegate/baking_scheduling.mli +++ b/src/proto_alpha/lib_delegate/baking_scheduling.mli @@ -62,8 +62,6 @@ val wait_next_event : loop_state -> (event option, error trace) result Lwt.t -val compute_next_round_time : state -> (Time.Protocol.t * Round.t) option - (** Returns the first round at the next level, at or after [earliest_round], whose baking slot belongs to one of our own delegates; also returns the corresponding delegate. Or returns diff --git a/src/proto_alpha/lib_delegate/baking_state.ml b/src/proto_alpha/lib_delegate/baking_state.ml index 7ac47ce40ef5..a9705c23dbf1 100644 --- a/src/proto_alpha/lib_delegate/baking_state.ml +++ b/src/proto_alpha/lib_delegate/baking_state.ml @@ -25,7 +25,6 @@ open Protocol open Alpha_context -open Protocol_client_context (** A consensus key (aka, a validator) is identified by its alias name, its public key, its public key hash, and its secret key. *) @@ -756,6 +755,61 @@ let create_cache () = round_timestamps = Round_timestamp_interval_cache.create cache_size_limit; } +(** Memoization wrapper for [Round.timestamp_of_round]. *) +let timestamp_of_round state ~predecessor_timestamp ~predecessor_round ~round = + let open Result_syntax in + let open Baking_cache in + let known_timestamps = state.global_state.cache.known_timestamps in + match + Timestamp_of_round_cache.find_opt + known_timestamps + (predecessor_timestamp, predecessor_round, round) + with + (* Compute and register the timestamp if not already existing. *) + | None -> + let* ts = + Environment.wrap_tzresult + @@ Protocol.Alpha_context.Round.timestamp_of_round + state.global_state.round_durations + ~predecessor_timestamp + ~predecessor_round + ~round + in + Timestamp_of_round_cache.replace + known_timestamps + (predecessor_timestamp, predecessor_round, round) + ts ; + return ts + (* If it already exists, just fetch from the memoization table. *) + | Some ts -> return ts + +let compute_next_round_time state = + let proposal = + match state.level_state.attestable_payload with + | None -> state.level_state.latest_proposal + | Some {proposal; _} -> proposal + in + if is_first_block_in_protocol proposal then None + else + match state.level_state.next_level_proposed_round with + | Some _proposed_round -> + (* TODO? do something, if we don't, we won't be able to + repropose a block at next level. *) + None + | None -> ( + let predecessor_timestamp = proposal.predecessor.shell.timestamp in + let predecessor_round = proposal.predecessor.round in + let next_round = Round.succ state.round_state.current_round in + match + timestamp_of_round + state + ~predecessor_timestamp + ~predecessor_round + ~round:next_round + with + | Ok timestamp -> Some (timestamp, next_round) + | _ -> assert false) + (* Pretty-printers *) let pp_validation_mode fmt = function diff --git a/src/proto_alpha/lib_delegate/baking_state.mli b/src/proto_alpha/lib_delegate/baking_state.mli index 037adb00dda4..18385f8ecb10 100644 --- a/src/proto_alpha/lib_delegate/baking_state.mli +++ b/src/proto_alpha/lib_delegate/baking_state.mli @@ -247,6 +247,19 @@ val compute_delegate_slots : val create_cache : unit -> cache +(** Memoization wrapper for [Round.timestamp_of_round]. *) +val timestamp_of_round : + state -> + predecessor_timestamp:Time.Protocol.t -> + predecessor_round:Round.t -> + round:Round.t -> + Time.Protocol.t tzresult + +(** From the current [state], the function returns an optional + association pair, which consists of the next round timestamp and its + round. *) +val compute_next_round_time : state -> (Time.Protocol.t * Round.t) option + val pp_validation_mode : Format.formatter -> validation_mode -> unit val pp_global_state : Format.formatter -> global_state -> unit -- GitLab From 9e4278b707820b68accd65e205b437d53b07efb9 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Thu, 18 Jan 2024 11:48:35 +0100 Subject: [PATCH 15/17] Alpha/Baker: add a timeout for fetching DAL attestations --- .../lib_delegate/baking_actions.ml | 49 ++++++++++++++++--- src/proto_alpha/lib_delegate/baking_events.ml | 13 +++++ 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 2a6fce7a641a..61b325680da9 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -572,24 +572,57 @@ let sign_consensus_votes_aux state votes kind ~level ~round = let operation : Operation.packed = {shell; protocol_data} in return_some (delegate, operation, level, round) in + let compute_dal_rpc_timeout state = + (* We set the timeout to a certain percent of the remaining time till the + end of the round. *) + let default = 0.2 in + match compute_next_round_time state with + | None -> (* corner case; we pick some small default value *) default + | Some (timestamp, _next_round) -> ( + let ts = Time.System.of_protocol_opt timestamp in + match ts with + | None -> default + | Some ts -> + let now = Time.System.now () in + let diff = Ptime.diff ts now |> Ptime.Span.to_float_s in + if diff < 0. then + (* We could output a warning, as this should not happen. *) + default + else diff *. 0.1) + in let get_dal_content delegate = only_if_dal_feature_enabled state ~default_value:None (fun dal_node_rpc_ctxt -> - let*! tz_res = - Node_rpc.get_attestable_slots - dal_node_rpc_ctxt - (fst delegate).public_key_hash - ~attested_level:(Int32.succ level) + let timeout = compute_dal_rpc_timeout state in + let*! result = + Lwt.pick + [ + (let*! () = Lwt_unix.sleep timeout in + Lwt.return `RPC_timeout); + (let*! tz_res = + Node_rpc.get_attestable_slots + dal_node_rpc_ctxt + (fst delegate).public_key_hash + ~attested_level:(Int32.succ level) + in + Lwt.return (`RPC_result tz_res)); + ] in - match tz_res with - | Error errs -> + match result with + | `RPC_timeout -> + let*! () = + Events.( + emit failed_to_get_dal_attestations_in_time (delegate, timeout)) + in + return_none + | `RPC_result (Error errs) -> let*! () = Events.(emit failed_to_get_dal_attestations (delegate, errs)) in return_none - | Ok res -> ( + | `RPC_result (Ok res) -> ( match res with | Tezos_dal_node_services.Types.Not_in_committee -> return_none | Attestable_slots {slots = attestation_flags; published_level} -> diff --git a/src/proto_alpha/lib_delegate/baking_events.ml b/src/proto_alpha/lib_delegate/baking_events.ml index 54ec36f67c3e..96b0b0715d26 100644 --- a/src/proto_alpha/lib_delegate/baking_events.ml +++ b/src/proto_alpha/lib_delegate/baking_events.ml @@ -612,6 +612,19 @@ module Actions = struct ~pp2:Error_monad.pp_print_trace ("trace", Error_monad.trace_encoding) + let failed_to_get_dal_attestations_in_time = + declare_2 + ~section + ~name:"failed_to_get_attestations_in_time" + ~level:Error + ~msg: + "unable to get DAL attestation for {delegate} within the {timeout}s \ + timeout" + ~pp1:Baking_state.pp_consensus_key_and_delegate + ("delegate", Baking_state.consensus_key_and_delegate_encoding) + ~pp2:Format.pp_print_float + ("timeout", Data_encoding.float) + let failed_to_inject_preattestation = declare_2 ~section -- GitLab From 431dee8fa431142a9af140b2e7ab1e83134bfea3 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Mon, 15 Jan 2024 13:27:01 +0100 Subject: [PATCH 16/17] Kaitai: update struct files --- .../files/alpha__operation.ksy | 20 +++++++++++++++++++ .../files/alpha__operation__contents.ksy | 20 +++++++++++++++++++ .../files/alpha__operation__contents_list.ksy | 20 +++++++++++++++++++ .../files/alpha__operation__protocol_data.ksy | 20 +++++++++++++++++++ .../files/alpha__operation__unsigned.ksy | 20 +++++++++++++++++++ .../alpha__operation_with_attestation.ksy | 20 +++++++++++++++++++ ...__operation_with_attestation__unsigned.ksy | 20 +++++++++++++++++++ 7 files changed, 140 insertions(+) diff --git a/contrib/kaitai-struct-files/files/alpha__operation.ksy b/contrib/kaitai-struct-files/files/alpha__operation.ksy index 42216b92f4fe..a8c35ca63e0b 100644 --- a/contrib/kaitai-struct-files/files/alpha__operation.ksy +++ b/contrib/kaitai-struct-files/files/alpha__operation.ksy @@ -88,6 +88,9 @@ types: - id: attestation type: attestation if: (alpha__inlined__attestation_mempool__contents_tag == alpha__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (alpha__inlined__attestation_mempool__contents_tag == alpha__inlined__attestation_mempool__contents_tag::attestation_with_dal) alpha__inlined__preattestation: seq: - id: alpha__inlined__preattestation @@ -132,6 +135,9 @@ types: - id: attestation type: attestation if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::attestation_with_dal) - id: double_preattestation_evidence type: double_preattestation_evidence if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::double_preattestation_evidence) @@ -274,6 +280,18 @@ types: type: s4 - id: block_payload_hash size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2 + - id: level + type: s4 + - id: round + type: s4 + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z ballot: seq: - id: source @@ -1477,6 +1495,7 @@ enums: 255: named alpha__inlined__attestation_mempool__contents_tag: 21: attestation + 23: attestation_with_dal alpha__inlined__preattestation__contents_tag: 20: preattestation alpha__michelson__v1__primitives: @@ -1887,6 +1906,7 @@ enums: 20: preattestation 21: attestation 22: dal_attestation + 23: attestation_with_dal 107: reveal 108: transaction 109: origination diff --git a/contrib/kaitai-struct-files/files/alpha__operation__contents.ksy b/contrib/kaitai-struct-files/files/alpha__operation__contents.ksy index c47bb86c1ce7..aa96f6eb2e10 100644 --- a/contrib/kaitai-struct-files/files/alpha__operation__contents.ksy +++ b/contrib/kaitai-struct-files/files/alpha__operation__contents.ksy @@ -88,6 +88,9 @@ types: - id: endorsement type: endorsement if: (alpha__inlined__endorsement_mempool__contents_tag == alpha__inlined__endorsement_mempool__contents_tag::endorsement) + - id: endorsement_with_dal + type: endorsement_with_dal + if: (alpha__inlined__endorsement_mempool__contents_tag == alpha__inlined__endorsement_mempool__contents_tag::endorsement_with_dal) alpha__inlined__preendorsement: seq: - id: alpha__inlined__preendorsement @@ -128,6 +131,9 @@ types: - id: endorsement type: endorsement if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::endorsement) + - id: endorsement_with_dal + type: endorsement_with_dal + if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::endorsement_with_dal) - id: double_preendorsement_evidence type: double_preendorsement_evidence if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::double_preendorsement_evidence) @@ -452,6 +458,18 @@ types: type: s4 - id: block_payload_hash size: 32 + endorsement_with_dal: + seq: + - id: slot + type: u2 + - id: level + type: s4 + - id: round + type: s4 + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z inbox__proof: seq: - id: level @@ -1454,6 +1472,7 @@ enums: 255: named alpha__inlined__endorsement_mempool__contents_tag: 21: endorsement + 23: endorsement_with_dal alpha__inlined__preendorsement__contents_tag: 20: preendorsement alpha__michelson__v1__primitives: @@ -1864,6 +1883,7 @@ enums: 20: preendorsement 21: endorsement 22: dal_attestation + 23: endorsement_with_dal 107: reveal 108: transaction 109: origination diff --git a/contrib/kaitai-struct-files/files/alpha__operation__contents_list.ksy b/contrib/kaitai-struct-files/files/alpha__operation__contents_list.ksy index 78c6a2afc703..612fa3b08c13 100644 --- a/contrib/kaitai-struct-files/files/alpha__operation__contents_list.ksy +++ b/contrib/kaitai-struct-files/files/alpha__operation__contents_list.ksy @@ -88,6 +88,9 @@ types: - id: endorsement type: endorsement if: (alpha__inlined__endorsement_mempool__contents_tag == alpha__inlined__endorsement_mempool__contents_tag::endorsement) + - id: endorsement_with_dal + type: endorsement_with_dal + if: (alpha__inlined__endorsement_mempool__contents_tag == alpha__inlined__endorsement_mempool__contents_tag::endorsement_with_dal) alpha__inlined__preendorsement: seq: - id: alpha__inlined__preendorsement @@ -132,6 +135,9 @@ types: - id: endorsement type: endorsement if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::endorsement) + - id: endorsement_with_dal + type: endorsement_with_dal + if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::endorsement_with_dal) - id: double_preendorsement_evidence type: double_preendorsement_evidence if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::double_preendorsement_evidence) @@ -456,6 +462,18 @@ types: type: s4 - id: block_payload_hash size: 32 + endorsement_with_dal: + seq: + - id: slot + type: u2 + - id: level + type: s4 + - id: round + type: s4 + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z inbox__proof: seq: - id: level @@ -1458,6 +1476,7 @@ enums: 255: named alpha__inlined__endorsement_mempool__contents_tag: 21: endorsement + 23: endorsement_with_dal alpha__inlined__preendorsement__contents_tag: 20: preendorsement alpha__michelson__v1__primitives: @@ -1868,6 +1887,7 @@ enums: 20: preendorsement 21: endorsement 22: dal_attestation + 23: endorsement_with_dal 107: reveal 108: transaction 109: origination diff --git a/contrib/kaitai-struct-files/files/alpha__operation__protocol_data.ksy b/contrib/kaitai-struct-files/files/alpha__operation__protocol_data.ksy index 58542eb7c47a..18296899f0b7 100644 --- a/contrib/kaitai-struct-files/files/alpha__operation__protocol_data.ksy +++ b/contrib/kaitai-struct-files/files/alpha__operation__protocol_data.ksy @@ -88,6 +88,9 @@ types: - id: attestation type: attestation if: (alpha__inlined__attestation_mempool__contents_tag == alpha__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (alpha__inlined__attestation_mempool__contents_tag == alpha__inlined__attestation_mempool__contents_tag::attestation_with_dal) alpha__inlined__preattestation: seq: - id: alpha__inlined__preattestation @@ -132,6 +135,9 @@ types: - id: attestation type: attestation if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::attestation_with_dal) - id: double_preattestation_evidence type: double_preattestation_evidence if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::double_preattestation_evidence) @@ -274,6 +280,18 @@ types: type: s4 - id: block_payload_hash size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2 + - id: level + type: s4 + - id: round + type: s4 + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z ballot: seq: - id: source @@ -1477,6 +1495,7 @@ enums: 255: named alpha__inlined__attestation_mempool__contents_tag: 21: attestation + 23: attestation_with_dal alpha__inlined__preattestation__contents_tag: 20: preattestation alpha__michelson__v1__primitives: @@ -1887,6 +1906,7 @@ enums: 20: preattestation 21: attestation 22: dal_attestation + 23: attestation_with_dal 107: reveal 108: transaction 109: origination diff --git a/contrib/kaitai-struct-files/files/alpha__operation__unsigned.ksy b/contrib/kaitai-struct-files/files/alpha__operation__unsigned.ksy index fda84fff4c4f..11b3ab049c5f 100644 --- a/contrib/kaitai-struct-files/files/alpha__operation__unsigned.ksy +++ b/contrib/kaitai-struct-files/files/alpha__operation__unsigned.ksy @@ -88,6 +88,9 @@ types: - id: endorsement type: endorsement if: (alpha__inlined__endorsement_mempool__contents_tag == alpha__inlined__endorsement_mempool__contents_tag::endorsement) + - id: endorsement_with_dal + type: endorsement_with_dal + if: (alpha__inlined__endorsement_mempool__contents_tag == alpha__inlined__endorsement_mempool__contents_tag::endorsement_with_dal) alpha__inlined__preendorsement: seq: - id: alpha__inlined__preendorsement @@ -128,6 +131,9 @@ types: - id: endorsement type: endorsement if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::endorsement) + - id: endorsement_with_dal + type: endorsement_with_dal + if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::endorsement_with_dal) - id: double_preendorsement_evidence type: double_preendorsement_evidence if: (alpha__operation_with_legacy_attestation_name__alpha__contents_tag == alpha__operation_with_legacy_attestation_name__alpha__contents_tag::double_preendorsement_evidence) @@ -463,6 +469,18 @@ types: type: s4 - id: block_payload_hash size: 32 + endorsement_with_dal: + seq: + - id: slot + type: u2 + - id: level + type: s4 + - id: round + type: s4 + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z inbox__proof: seq: - id: level @@ -1465,6 +1483,7 @@ enums: 255: named alpha__inlined__endorsement_mempool__contents_tag: 21: endorsement + 23: endorsement_with_dal alpha__inlined__preendorsement__contents_tag: 20: preendorsement alpha__michelson__v1__primitives: @@ -1875,6 +1894,7 @@ enums: 20: preendorsement 21: endorsement 22: dal_attestation + 23: endorsement_with_dal 107: reveal 108: transaction 109: origination diff --git a/contrib/kaitai-struct-files/files/alpha__operation_with_attestation.ksy b/contrib/kaitai-struct-files/files/alpha__operation_with_attestation.ksy index 2568df8f21f5..d95f125c2edc 100644 --- a/contrib/kaitai-struct-files/files/alpha__operation_with_attestation.ksy +++ b/contrib/kaitai-struct-files/files/alpha__operation_with_attestation.ksy @@ -88,6 +88,9 @@ types: - id: attestation type: attestation if: (alpha__inlined__attestation_mempool__contents_tag == alpha__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (alpha__inlined__attestation_mempool__contents_tag == alpha__inlined__attestation_mempool__contents_tag::attestation_with_dal) alpha__inlined__preattestation: seq: - id: alpha__inlined__preattestation @@ -139,6 +142,9 @@ types: - id: attestation type: attestation if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::attestation_with_dal) - id: double_preattestation_evidence type: double_preattestation_evidence if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::double_preattestation_evidence) @@ -274,6 +280,18 @@ types: type: s4 - id: block_payload_hash size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2 + - id: level + type: s4 + - id: round + type: s4 + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z ballot: seq: - id: source @@ -1477,6 +1495,7 @@ enums: 255: named alpha__inlined__attestation_mempool__contents_tag: 21: attestation + 23: attestation_with_dal alpha__inlined__preattestation__contents_tag: 20: preattestation alpha__michelson__v1__primitives: @@ -1887,6 +1906,7 @@ enums: 20: preattestation 21: attestation 22: dal_attestation + 23: attestation_with_dal 107: reveal 108: transaction 109: origination diff --git a/contrib/kaitai-struct-files/files/alpha__operation_with_attestation__unsigned.ksy b/contrib/kaitai-struct-files/files/alpha__operation_with_attestation__unsigned.ksy index a2f32e036ac9..3cb07c64cca2 100644 --- a/contrib/kaitai-struct-files/files/alpha__operation_with_attestation__unsigned.ksy +++ b/contrib/kaitai-struct-files/files/alpha__operation_with_attestation__unsigned.ksy @@ -88,6 +88,9 @@ types: - id: attestation type: attestation if: (alpha__inlined__attestation_mempool__contents_tag == alpha__inlined__attestation_mempool__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (alpha__inlined__attestation_mempool__contents_tag == alpha__inlined__attestation_mempool__contents_tag::attestation_with_dal) alpha__inlined__preattestation: seq: - id: alpha__inlined__preattestation @@ -128,6 +131,9 @@ types: - id: attestation type: attestation if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::attestation) + - id: attestation_with_dal + type: attestation_with_dal + if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::attestation_with_dal) - id: double_preattestation_evidence type: double_preattestation_evidence if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::double_preattestation_evidence) @@ -270,6 +276,18 @@ types: type: s4 - id: block_payload_hash size: 32 + attestation_with_dal: + seq: + - id: slot + type: u2 + - id: level + type: s4 + - id: round + type: s4 + - id: block_payload_hash + size: 32 + - id: dal_attestation + type: z ballot: seq: - id: source @@ -1465,6 +1483,7 @@ enums: 255: named alpha__inlined__attestation_mempool__contents_tag: 21: attestation + 23: attestation_with_dal alpha__inlined__preattestation__contents_tag: 20: preattestation alpha__michelson__v1__primitives: @@ -1875,6 +1894,7 @@ enums: 20: preattestation 21: attestation 22: dal_attestation + 23: attestation_with_dal 107: reveal 108: transaction 109: origination -- GitLab From 2556b031e3c83ab3d2451ef66c2fd2dc579999f9 Mon Sep 17 00:00:00 2001 From: Eugen Zalinescu Date: Mon, 22 Jan 2024 10:46:30 +0100 Subject: [PATCH 17/17] Docs/Alpha: update CHANGES --- docs/protocols/alpha.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index 7731bf7581ab..86577218c1bf 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -35,6 +35,13 @@ Data Availability Layer (ongoing) - Optimize the slot header publication operation by memoizing the cryptobox. (MR :gl:`!11594`) +- Introduced a new optional field ``dal_content`` to consensus attestation + operations. This is treated in the same way as the content of DAL attestation + operations, rendering these obsolete. The existing encoding of consensus + attestations remains unchanged when this field is not present. A new encoding + was introduced for the case when the field is present. The two cases are + distinguished via an encoding tag. (MR :gl:`!11462`) + Adaptive Issuance (ongoing) ---------------------------- -- GitLab