From 2b86980c062ca3ba381ed4d1e7ec610a70554db2 Mon Sep 17 00:00:00 2001 From: Adam Allombert-Goget Date: Fri, 28 Mar 2025 22:52:12 +0100 Subject: [PATCH 1/3] proto: add Preattestations_aggregate operation --- .../lib_client/operation_result.ml | 17 +++++ .../lib_injector/injector_plugin.ml | 1 + src/proto_alpha/lib_plugin/mempool.ml | 16 +++-- .../lib_protocol/alpha_context.mli | 15 +++++ src/proto_alpha/lib_protocol/apply.ml | 3 + src/proto_alpha/lib_protocol/apply_results.ml | 9 +++ .../lib_protocol/apply_results.mli | 6 ++ .../lib_protocol/operation_repr.ml | 26 +++++++- .../lib_protocol/operation_repr.mli | 27 ++++++-- .../lib_protocol/test/helpers/block.ml | 1 + .../lib_protocol/test/helpers/op.ml | 63 +++++++++++++++++++ .../lib_protocol/test/helpers/op.mli | 19 ++++++ .../test/helpers/slashing_helpers.ml | 7 ++- .../validate/generator_descriptors.ml | 35 +++++++++++ .../validate/generator_descriptors.mli | 1 + .../test/integration/validate/test_sanity.ml | 3 + src/proto_alpha/lib_protocol/validate.ml | 12 +++- .../lib_sc_rollup_node/sc_rollup_injector.ml | 1 + 18 files changed, 247 insertions(+), 15 deletions(-) diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index e1d4ffac56c7..749d128b0b94 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -1039,6 +1039,23 @@ let pp_contents_and_result : Consensus_key.pp {delegate; consensus_pkh = consensus_key} consensus_power + | ( Preattestations_aggregate {consensus_content = {level; _}; _}, + Preattestations_aggregate_result + {balance_updates; committee; consensus_power} ) -> + Format.fprintf + ppf + "@[Preattestations aggregate:@,\ + Level: %a@,\ + Balance updates:%a@,\ + Delegates: %a@,\ + Consensus Power: %d@]" + Raw_level.pp + level + pp_balance_updates + balance_updates + (Format.pp_print_list Consensus_key.pp) + committee + consensus_power | ( Attestations_aggregate {consensus_content = {level; _}; _}, Attestations_aggregate_result {balance_updates; committee; consensus_power} ) -> diff --git a/src/proto_alpha/lib_injector/injector_plugin.ml b/src/proto_alpha/lib_injector/injector_plugin.ml index 1818a39f8187..1343d761b0de 100644 --- a/src/proto_alpha/lib_injector/injector_plugin.ml +++ b/src/proto_alpha/lib_injector/injector_plugin.ml @@ -155,6 +155,7 @@ module Proto_client = struct | Preattestation_result _ -> Successful | Attestation_result _ -> Successful | Attestations_aggregate_result _ -> Successful + | Preattestations_aggregate_result _ -> Successful | Seed_nonce_revelation_result _ -> Successful | Vdf_revelation_result _ -> Successful | Double_attestation_evidence_result _ -> Successful diff --git a/src/proto_alpha/lib_plugin/mempool.ml b/src/proto_alpha/lib_plugin/mempool.ml index 02dd68d80ac3..36ad11a1ddae 100644 --- a/src/proto_alpha/lib_plugin/mempool.ml +++ b/src/proto_alpha/lib_plugin/mempool.ml @@ -552,6 +552,10 @@ let pre_filter info config {level = consensus_content.level; round = consensus_content.round} in prefilter_consensus_operation info config level_and_round + | Single (Preattestations_aggregate _) -> + (* Aggregate are built at baking time and shouldn't be broadcasted between + mempools. *) + return (`Refused [Environment.wrap_tzerror Wrong_operation]) | Single (Attestations_aggregate _) -> (* Aggregate are built at baking time and shouldn't be broadcasted between mempools. *) @@ -694,11 +698,12 @@ let find_manager {shell = _; protocol_data = Operation_data {contents; _}} = | Single (Manager_operation {source; _}) -> Some source | Cons (Manager_operation {source; _}, _) -> Some source | Single - ( Preattestation _ | Attestation _ | Attestations_aggregate _ - | Proposals _ | Ballot _ | Seed_nonce_revelation _ | Vdf_revelation _ - | Double_baking_evidence _ | Double_preattestation_evidence _ - | Double_attestation_evidence _ | Dal_entrapment_evidence _ - | Activate_account _ | Drain_delegate _ | Failing_noop _ ) -> + ( Preattestation _ | Attestation _ | Preattestations_aggregate _ + | Attestations_aggregate _ | Proposals _ | Ballot _ + | Seed_nonce_revelation _ | Vdf_revelation _ | Double_baking_evidence _ + | Double_preattestation_evidence _ | Double_attestation_evidence _ + | Dal_entrapment_evidence _ | Activate_account _ | Drain_delegate _ + | Failing_noop _ ) -> None (* The purpose of this module is to offer a version of @@ -825,6 +830,7 @@ let sources_from_operation ctxt } ) -> return @@ map_pkh_env [delegate; consensus_pkh] | Error _ -> return_nil) + | Single (Preattestations_aggregate {consensus_content; committee}) | Single (Attestations_aggregate {consensus_content; committee}) -> let level = Level.from_raw ctxt consensus_content.level in let* sources = diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 23c066b2adff..f2d10561c597 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -4539,12 +4539,17 @@ module Kind : sig type attestation_consensus_kind = Attestation_consensus_kind + type preattestations_aggregate_consensus_kind = + | Preattestations_aggregate_consensus_kind + type attestations_aggregate_consensus_kind = | Attestations_aggregate_consensus_kind type 'a consensus = | Preattestation_kind : preattestation_consensus_kind consensus | Attestation_kind : attestation_consensus_kind consensus + | Preattestations_aggregate_kind + : preattestations_aggregate_consensus_kind consensus | Attestations_aggregate_kind : attestations_aggregate_consensus_kind consensus @@ -4552,6 +4557,9 @@ module Kind : sig type attestation = attestation_consensus_kind consensus + type preattestations_aggregate = + preattestations_aggregate_consensus_kind consensus + type attestations_aggregate = attestations_aggregate_consensus_kind consensus type seed_nonce_revelation = Seed_nonce_revelation_kind @@ -4657,6 +4665,8 @@ end type 'a consensus_operation_type = | Attestation : Kind.attestation consensus_operation_type | Preattestation : Kind.preattestation consensus_operation_type + | Preattestations_aggregate + : Kind.preattestations_aggregate consensus_operation_type | Attestations_aggregate : Kind.attestations_aggregate consensus_operation_type @@ -4705,6 +4715,11 @@ and _ contents = dal_content : dal_content option; } -> Kind.attestation contents + | Preattestations_aggregate : { + consensus_content : consensus_aggregate_content; + committee : Slot.t list; + } + -> Kind.preattestations_aggregate contents | Attestations_aggregate : { consensus_content : consensus_aggregate_content; committee : Slot.t list; diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index fce347a7ecc8..694e8c808893 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2256,6 +2256,7 @@ let record_operation (type kind) ctxt hash (operation : kind operation) : match operation.protocol_data.contents with | Single (Preattestation _) -> ctxt | Single (Attestation _) -> ctxt + | Single (Preattestations_aggregate _) -> ctxt | Single (Attestations_aggregate _) -> ctxt | Single ( Failing_noop _ | Proposals _ | Ballot _ | Seed_nonce_revelation _ @@ -2546,6 +2547,8 @@ let apply_contents_list (type kind) ctxt chain_id (mode : mode) record_preattestation ctxt mode consensus_content | Single (Attestation {consensus_content; dal_content}) -> record_attestation ctxt mode consensus_content dal_content + | Single (Preattestations_aggregate _) -> + tzfail Validate_errors.Consensus.Aggregate_not_implemented | Single (Attestations_aggregate {committee; _}) -> let*? () = error_unless diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index ea59262997a4..bc2b84dd450f 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -887,6 +887,12 @@ type 'kind contents_result = consensus_power : int; } -> Kind.attestation contents_result + | Preattestations_aggregate_result : { + balance_updates : Receipt.balance_updates; + committee : Consensus_key.t list; + consensus_power : int; + } + -> Kind.preattestations_aggregate contents_result | Attestations_aggregate_result : { balance_updates : Receipt.balance_updates; committee : Consensus_key.t list; @@ -1435,6 +1441,7 @@ module Encoding = struct {op with operation_result = Failed (kind, errs)})) | Contents_result (Preattestation_result _) -> None | Contents_result (Attestation_result _) -> None + | Contents_result (Preattestations_aggregate_result _) -> None | Contents_result (Attestations_aggregate_result _) -> None | Contents_result Ballot_result -> None | Contents_result (Seed_nonce_revelation_result _) -> None @@ -1909,6 +1916,8 @@ let kind_equal : | Attestation _, _ -> None | Preattestation _, Preattestation_result _ -> Some Eq | Preattestation _, _ -> None + | Preattestations_aggregate _, Preattestations_aggregate_result _ -> Some Eq + | Preattestations_aggregate _, _ -> None | Attestations_aggregate _, Attestations_aggregate_result _ -> Some Eq | Attestations_aggregate _, _ -> None | Seed_nonce_revelation _, Seed_nonce_revelation_result _ -> Some Eq diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 845cfff47b08..4d1d429f93c6 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -73,6 +73,12 @@ and 'kind contents_result = consensus_power : int; } -> Kind.attestation contents_result + | Preattestations_aggregate_result : { + balance_updates : Receipt.balance_updates; + committee : Consensus_key.t list; + consensus_power : int; + } + -> Kind.preattestations_aggregate contents_result | Attestations_aggregate_result : { balance_updates : Receipt.balance_updates; committee : Consensus_key.t list; diff --git a/src/proto_alpha/lib_protocol/operation_repr.ml b/src/proto_alpha/lib_protocol/operation_repr.ml index afffce57b7df..769ac2b44e6f 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -32,12 +32,17 @@ module Kind = struct type attestation_consensus_kind = Attestation_consensus_kind + type preattestations_aggregate_consensus_kind = + | Preattestations_aggregate_consensus_kind + type attestations_aggregate_consensus_kind = | Attestations_aggregate_consensus_kind type 'a consensus = | Preattestation_kind : preattestation_consensus_kind consensus | Attestation_kind : attestation_consensus_kind consensus + | Preattestations_aggregate_kind + : preattestations_aggregate_consensus_kind consensus | Attestations_aggregate_kind : attestations_aggregate_consensus_kind consensus @@ -45,6 +50,9 @@ module Kind = struct type attestation = attestation_consensus_kind consensus + type preattestations_aggregate = + preattestations_aggregate_consensus_kind consensus + type attestations_aggregate = attestations_aggregate_consensus_kind consensus type seed_nonce_revelation = Seed_nonce_revelation_kind @@ -148,6 +156,8 @@ end type 'a consensus_operation_type = | Attestation : Kind.attestation consensus_operation_type | Preattestation : Kind.preattestation consensus_operation_type + | Preattestations_aggregate + : Kind.preattestations_aggregate consensus_operation_type | Attestations_aggregate : Kind.attestations_aggregate consensus_operation_type @@ -279,6 +289,11 @@ and _ contents = dal_content : dal_content option; } -> Kind.attestation contents + | Preattestations_aggregate : { + consensus_content : consensus_aggregate_content; + committee : Slot_repr.t list; + } + -> Kind.preattestations_aggregate contents | Attestations_aggregate : { consensus_content : consensus_aggregate_content; committee : Slot_repr.t list; @@ -1927,6 +1942,7 @@ let acceptable_pass (op : packed_operation) = | Single (Failing_noop _) -> None | Single (Preattestation _) -> Some consensus_pass | Single (Attestation _) -> Some consensus_pass + | Single (Preattestations_aggregate _) -> Some consensus_pass | Single (Attestations_aggregate _) -> Some consensus_pass | Single (Proposals _) -> Some voting_pass | Single (Ballot _) -> Some voting_pass @@ -2031,7 +2047,8 @@ let check_signature (type kind) encoding key chain_id (op : kind operation) = | Vdf_revelation _ | Double_attestation_evidence _ | Double_preattestation_evidence _ | Double_baking_evidence _ | Dal_entrapment_evidence _ | Activate_account _ | Drain_delegate _ - | Manager_operation _ | Attestations_aggregate _ ) -> + | Manager_operation _ | Preattestations_aggregate _ + | Attestations_aggregate _ ) -> Generic_operation | Cons (Manager_operation _, _ops) -> Generic_operation in @@ -2111,6 +2128,8 @@ let equal_contents_kind : type a b. a contents -> b contents -> (a, b) eq option | Preattestation _, _ -> None | Attestation _, Attestation _ -> Some Eq | Attestation _, _ -> None + | Preattestations_aggregate _, Preattestations_aggregate _ -> Some Eq + | Preattestations_aggregate _, _ -> None | Attestations_aggregate _, Attestations_aggregate _ -> Some Eq | Attestations_aggregate _, _ -> None | Seed_nonce_revelation _, Seed_nonce_revelation _ -> Some Eq @@ -2476,6 +2495,11 @@ let weight_of : packed_operation -> operation_weight = ( Consensus, Weight_attestation (attestation_infos_from_content consensus_content dal_content) ) + | Single (Preattestations_aggregate {consensus_content; committee}) -> + let aggregate_infos = + aggregate_infos_from_content consensus_content committee + in + W (Consensus, Weight_attestations_aggregate aggregate_infos) | Single (Attestations_aggregate {consensus_content; committee}) -> let aggregate_infos = aggregate_infos_from_content consensus_content committee diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index 8e02274bb133..4257e2dba6f6 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -68,12 +68,17 @@ module Kind : sig type attestation_consensus_kind = Attestation_consensus_kind + type preattestations_aggregate_consensus_kind = + | Preattestations_aggregate_consensus_kind + type attestations_aggregate_consensus_kind = | Attestations_aggregate_consensus_kind type 'a consensus = | Preattestation_kind : preattestation_consensus_kind consensus | Attestation_kind : attestation_consensus_kind consensus + | Preattestations_aggregate_kind + : preattestations_aggregate_consensus_kind consensus | Attestations_aggregate_kind : attestations_aggregate_consensus_kind consensus @@ -81,6 +86,9 @@ module Kind : sig type attestation = attestation_consensus_kind consensus + type preattestations_aggregate = + preattestations_aggregate_consensus_kind consensus + type attestations_aggregate = attestations_aggregate_consensus_kind consensus type seed_nonce_revelation = Seed_nonce_revelation_kind @@ -184,6 +192,8 @@ end type 'a consensus_operation_type = | Attestation : Kind.attestation consensus_operation_type | Preattestation : Kind.preattestation consensus_operation_type + | Preattestations_aggregate + : Kind.preattestations_aggregate consensus_operation_type | Attestations_aggregate : Kind.attestations_aggregate consensus_operation_type @@ -273,6 +283,12 @@ and _ contents = dal_content : dal_content option; } -> Kind.attestation contents + (* Aggregate of preattestations. *) + | Preattestations_aggregate : { + consensus_content : consensus_aggregate_content; + committee : Slot_repr.t list; + } + -> Kind.preattestations_aggregate contents (* Aggregate of attestations without dal_content. *) | Attestations_aggregate : { consensus_content : consensus_aggregate_content; @@ -637,11 +653,12 @@ val compare_by_passes : packed_operation -> packed_operation -> int The global order is as follows: - {!Attestations_aggregate}, {!Attestation} and {!Preattestation} > - {!Proposals} > {!Ballot} > {!Double_preattestation_evidence} > - {!Double_attestation_evidence} > {!Double_baking_evidence} > - {!Dal_entrapment_evidence} > {!Vdf_revelation} > {!Seed_nonce_revelation} > - {!Activate_account} > {!Drain_delegate} > {!Manager_operation}. + {!Attestations_aggregate}, {!Preattestations_aggregate}, {!Attestation} and + {!Preattestation} > {!Proposals} > {!Ballot} > + {!Double_preattestation_evidence} > {!Double_attestation_evidence} > + {!Double_baking_evidence} > {!Dal_entrapment_evidence} > {!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 diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 7848833a0172..954faaac3d08 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -1168,6 +1168,7 @@ let balance_updates_of_single_content : | Proposals_result | Ballot_result -> [] | Preattestation_result {balance_updates; _} | Attestation_result {balance_updates; _} + | Preattestations_aggregate_result {balance_updates; _} | Attestations_aggregate_result {balance_updates; _} | Seed_nonce_revelation_result balance_updates | Vdf_revelation_result balance_updates diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index 71bac6bd8874..ae000bf57d48 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -172,6 +172,37 @@ let aggregate attestations = in {shell; protocol_data} +let aggregate_preattestations preattestations = + let aggregate_content = + List.fold_left + (fun acc ({shell; protocol_data = {contents; signature}} : _ Operation.t) -> + match (contents, signature) with + | Single (Preattestation consensus_content), Some (Bls bls_sig) -> ( + let {slot; _} = consensus_content in + match acc with + | Some (shell, proposal, slots, signatures) -> + Some (shell, proposal, slot :: slots, bls_sig :: signatures) + | None -> + let {level; round; block_payload_hash; _} = consensus_content in + let proposal = {level; round; block_payload_hash} in + Some (shell, proposal, [slot], [bls_sig])) + | _, _ -> acc) + None + preattestations + in + let open Option_syntax in + let* shell, consensus_content, committee, signatures = aggregate_content in + let+ signature = + Bls12_381_signature.MinPk.aggregate_signature_opt signatures + in + let contents = + Single (Preattestations_aggregate {consensus_content; committee}) + in + let protocol_data = + Operation_data {contents; signature = Some (Bls signature)} + in + {shell; protocol_data} + let attestation ?delegate ?slot ?level ?round ?block_payload_hash ?dal_content ?branch attested_block = let open Lwt_result_syntax in @@ -256,6 +287,38 @@ let preattestation ?delegate ?slot ?level ?round ?block_payload_hash ?branch in return (Operation.pack op) +let preattestations_aggregate ?committee ?level ?round ?block_payload_hash + ?branch attested_block = + let open Lwt_result_syntax in + let* committee = + match committee with + | Some committee -> return committee + | None -> + let* attesters = Context.get_attesters (B attested_block) in + return + @@ List.filter_map + (fun attester -> + match attester.Plugin.RPC.Validators.consensus_key with + | Bls _ -> Some attester.delegate + | _ -> None) + attesters + in + let* preattestations = + List.map_es + (fun delegate -> + raw_preattestation + ~delegate + ?level + ?round + ?block_payload_hash + ?branch + attested_block) + committee + in + match aggregate_preattestations preattestations with + | Some preattestations_aggregate -> return preattestations_aggregate + | None -> failwith "no Bls delegate found" + let sign ?watermark ctxt sk branch (Contents_list contents) = let open Lwt_result_syntax in let* op = sign ctxt ?watermark sk branch contents in diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index 7c5779656dff..2af3f847af52 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -133,6 +133,25 @@ val preattestation : Block.t -> Operation.packed tzresult Lwt.t +(** Create a packed preattestations_aggregate that is expected for a given + [Block.t]. Block context is expected to include at least one delegate with a + BLS key (or a registered consensus keys). *) +val preattestations_aggregate : + ?committee:public_key_hash list -> + ?level:Raw_level.t -> + ?round:Round.t -> + ?block_payload_hash:Block_payload_hash.t -> + ?branch:Block_hash.t -> + Block.t -> + Operation.packed tzresult Lwt.t + +(** Aggregate a list of preattestations in a single Preattestations_aggregate. + Preattestations signed by non-bls delegates are ignored. Evaluates to {!None} if + no bls-signed attestations are found or if signature_aggregation failed. *) +val aggregate_preattestations : + Kind.preattestation_consensus_kind Kind.consensus operation trace -> + Operation.packed option + type gas_limit = | Max (** Max corresponds to the [max_gas_limit_per_operation] constant. *) | High diff --git a/src/proto_alpha/lib_protocol/test/helpers/slashing_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/slashing_helpers.ml index 7732626dde9c..17593d655867 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/slashing_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/slashing_helpers.ml @@ -50,7 +50,12 @@ module Misbehaviour_repr = struct match duplicate_op.protocol_data.contents with | Single (Preattestation {level; round; _}) -> (level, round, Double_preattesting) - | Single (Attestation {consensus_content = {level; round; _}; _}) + | Single (Attestation {consensus_content = {level; round; _}; _}) -> + (level, round, Double_attesting) + | Single + (Preattestations_aggregate {consensus_content = {level; round; _}; _}) + -> + (level, round, Double_preattesting) | Single (Attestations_aggregate {consensus_content = {level; round; _}; _}) -> (level, round, Double_attesting) diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.ml b/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.ml index c82f7520c2e8..68cc1a482129 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.ml @@ -676,6 +676,37 @@ let attestations_aggregate_descriptor = | None -> return_nil); } +let preattestations_aggregate_descriptor = + let open Lwt_result_syntax in + { + parameters = Fun.id; + required_cycle = (fun _ -> 1); + required_block = (fun _ -> 1); + prelude = (On 1, fun state -> return ([], state)); + opt_prelude = None; + candidates_generator = + (fun state -> + let open Lwt_result_syntax in + let* preattestations = + List.filter_map_es + (fun (delegate, consensus_key_opt) -> + let* slots_opt = + Context.get_attester_slot (B state.block) delegate + in + let delegate = Option.value ~default:delegate consensus_key_opt in + let* signer = Account.find delegate in + match (slots_opt, signer.sk) with + | Some (_ :: _), Bls _ -> + let* op = Op.raw_preattestation ~delegate state.block in + return (Some op) + | _, _ -> return_none) + state.delegates + in + match Op.aggregate_preattestations preattestations with + | Some op -> return [op] + | None -> return_nil); + } + module Manager = Manager_operation_helpers let required_nb_account = 7 @@ -831,6 +862,7 @@ type op_kind = | KAttestation | KPreattestation | KAttestations_aggregate + | KPreattestations_aggregate | KBallotExp | KBallotProm | KProposals @@ -849,6 +881,7 @@ let op_kind_of_packed_operation op = | Single (Preattestation _) -> KPreattestation | Single (Attestation _) -> KAttestation | Single (Attestations_aggregate _) -> KAttestations_aggregate + | Single (Preattestations_aggregate _) -> KPreattestations_aggregate | Single (Seed_nonce_revelation _) -> KNonce | Single (Vdf_revelation _) -> KVdf | Single (Double_attestation_evidence _) -> KDbl_consensus @@ -869,6 +902,7 @@ let pp_op_kind fmt kind = (match kind with | KManager -> "manager" | KAttestations_aggregate -> "attestations_aggregate" + | KPreattestations_aggregate -> "preattestations_aggregate" | KAttestation -> "attestation" | KPreattestation -> "preattestation" | KBallotExp -> "ballot" @@ -887,6 +921,7 @@ let descriptor_of ~nb_bootstrap ~max_batch_size = function | KAttestation -> attestation_descriptor | KAttestations_aggregate -> attestations_aggregate_descriptor | KPreattestation -> preattestation_descriptor + | KPreattestations_aggregate -> preattestations_aggregate_descriptor | KBallotExp -> ballot_exploration_descriptor | KBallotProm -> ballot_promotion_descriptor | KProposals -> proposal_descriptor diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.mli b/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.mli index 809f0342d1ef..ce23fb42e91e 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.mli +++ b/src/proto_alpha/lib_protocol/test/integration/validate/generator_descriptors.mli @@ -124,6 +124,7 @@ type op_kind = | KAttestation | KPreattestation | KAttestations_aggregate + | KPreattestations_aggregate | KBallotExp | KBallotProm | KProposals diff --git a/src/proto_alpha/lib_protocol/test/integration/validate/test_sanity.ml b/src/proto_alpha/lib_protocol/test/integration/validate/test_sanity.ml index cde4789fe309..ad39211e9e07 100644 --- a/src/proto_alpha/lib_protocol/test/integration/validate/test_sanity.ml +++ b/src/proto_alpha/lib_protocol/test/integration/validate/test_sanity.ml @@ -112,6 +112,9 @@ let covalidation_sanity () = | Single (Attestations_aggregate _), KAttestations_aggregate -> return_unit | Single (Attestations_aggregate _), _ -> assert false + | Single (Preattestations_aggregate _), KPreattestations_aggregate -> + return_unit + | Single (Preattestations_aggregate _), _ -> assert false | Single (Seed_nonce_revelation _), KNonce -> return_unit | Single (Seed_nonce_revelation _), _ -> assert false | Single (Vdf_revelation _), KVdf -> return_unit diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 71c2651884b3..fb4c1be71f7c 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -1558,6 +1558,8 @@ module Anonymous = struct | ( Single (Attestation {consensus_content = e1; dal_content = _}), Single (Attestation {consensus_content = e2; dal_content = _}) ) -> return (e1, e2, Misbehaviour.Double_attesting) + | ( Single (Preattestations_aggregate _), + Single (Preattestations_aggregate _) ) | Single (Attestations_aggregate _), Single (Attestations_aggregate _) -> (* TODO : https://gitlab.com/tezos/tezos/-/issues/7598 handle denunciation for aggregates. *) @@ -3043,6 +3045,8 @@ let check_operation ?(check_signature = true) info (type kind) Consensus.check_attestation info ~check_signature operation in return_unit + | Single (Preattestations_aggregate _) -> + tzfail Validate_errors.Consensus.Aggregate_in_mempool | Single (Attestations_aggregate _) -> tzfail Validate_errors.Consensus.Aggregate_in_mempool | Single (Proposals _) -> @@ -3102,7 +3106,7 @@ let check_operation_conflict (type kind) operation_conflict_state oph operation_conflict_state oph operation - | Single (Attestations_aggregate _) -> + | Single (Preattestations_aggregate _) | Single (Attestations_aggregate _) -> (* This case is unreachable because the operation is assumed to be valid, and aggregates are never valid in mempools. *) assert false @@ -3166,7 +3170,7 @@ let add_valid_operation operation_conflict_state oph (type kind) Consensus.add_preattestation operation_conflict_state oph operation | Single (Attestation _) -> Consensus.add_attestation operation_conflict_state oph operation - | Single (Attestations_aggregate _) -> + | Single (Preattestations_aggregate _) | Single (Attestations_aggregate _) -> (* This case is unreachable because the operation is assumed to be valid, and aggregates are never valid in mempools. *) assert false @@ -3218,7 +3222,7 @@ let remove_operation operation_conflict_state (type kind) Consensus.remove_preattestation operation_conflict_state operation | Single (Attestation _) -> Consensus.remove_attestation operation_conflict_state operation - | Single (Attestations_aggregate _) -> + | Single (Preattestations_aggregate _) | Single (Attestations_aggregate _) -> (* This case is unreachable because the operation is assumed to be valid, and aggregates are never valid in mempools. *) assert false @@ -3322,6 +3326,8 @@ let validate_operation ?(check_signature = true) block_state oph operation + | Single (Preattestations_aggregate _) -> + tzfail Validate_errors.Consensus.Aggregate_not_implemented | Single (Attestations_aggregate _) -> Consensus.validate_attestations_aggregate ~check_signature diff --git a/src/proto_alpha/lib_sc_rollup_node/sc_rollup_injector.ml b/src/proto_alpha/lib_sc_rollup_node/sc_rollup_injector.ml index 05ffd2e39309..02fdc9bf91ca 100644 --- a/src/proto_alpha/lib_sc_rollup_node/sc_rollup_injector.ml +++ b/src/proto_alpha/lib_sc_rollup_node/sc_rollup_injector.ml @@ -207,6 +207,7 @@ module Proto_client = struct match op_result with | Preattestation_result _ -> Successful | Attestation_result _ -> Successful + | Preattestations_aggregate_result _ -> Successful | Attestations_aggregate_result _ -> Successful | Seed_nonce_revelation_result _ -> Successful | Vdf_revelation_result _ -> Successful -- GitLab From 05d4fe7a43b9ef4ad492d511c1f1be2502208606 Mon Sep 17 00:00:00 2001 From: Adam Allombert-Goget Date: Wed, 9 Apr 2025 15:48:27 +0200 Subject: [PATCH 2/3] proto: add encodings for Preattestations_aggregates --- .../lib_protocol/alpha_context.mli | 2 ++ src/proto_alpha/lib_protocol/apply_results.ml | 32 +++++++++++++++++-- .../lib_protocol/operation_repr.ml | 23 +++++++++++++ .../lib_protocol/operation_repr.mli | 2 ++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index f2d10561c597..9958208f7dc3 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -5012,6 +5012,8 @@ module Operation : sig val attestations_aggregate_case : Kind.attestations_aggregate case + val preattestations_aggregate_case : Kind.preattestations_aggregate case + val attestation_with_dal_case : Kind.attestation case val seed_nonce_revelation_case : Kind.seed_nonce_revelation case diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index bc2b84dd450f..3e98d50c8234 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -1164,6 +1164,32 @@ module Encoding = struct {balance_updates; committee; consensus_power}); } + let preattestations_aggregate_case = + Case + { + op_case = Operation.Encoding.preattestations_aggregate_case; + encoding = consensus_aggregate_result_encoding; + select = + (function + | Contents_result (Preattestations_aggregate_result _ as op) -> + Some op + | _ -> None); + mselect = + (function + | Contents_and_result ((Preattestations_aggregate _ as op), res) -> + Some (op, res) + | _ -> None); + proj = + (function + | Preattestations_aggregate_result + {balance_updates; committee; consensus_power} -> + (balance_updates, committee, consensus_power)); + inj = + (fun (balance_updates, committee, consensus_power) -> + Preattestations_aggregate_result + {balance_updates; committee; consensus_power}); + } + let seed_nonce_revelation_case = Case { @@ -1754,9 +1780,9 @@ let common_cases = let contents_cases = let open Encoding in attestation_case :: attestation_with_dal_case :: preattestation_case - :: attestations_aggregate_case :: double_attestation_evidence_case - :: double_preattestation_evidence_case :: dal_entrapment_evidence_case - :: common_cases + :: attestations_aggregate_case :: preattestations_aggregate_case + :: double_attestation_evidence_case :: double_preattestation_evidence_case + :: dal_entrapment_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 769ac2b44e6f..0fb269978f8c 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/operation_repr.ml @@ -1263,6 +1263,28 @@ module Encoding = struct Attestations_aggregate {consensus_content; committee}); } + let preattestations_aggregate_encoding = + obj2 + (req "consensus_content" consensus_aggregate_content_encoding) + (req "committee" (list Slot_repr.encoding)) + + let preattestations_aggregate_case = + Case + { + tag = 30; + name = "preattestations_aggregate"; + encoding = preattestations_aggregate_encoding; + select = + (function + | Contents (Preattestations_aggregate _ as op) -> Some op | _ -> None); + proj = + (fun (Preattestations_aggregate {consensus_content; committee}) -> + (consensus_content, committee)); + inj = + (fun (consensus_content, committee) -> + Preattestations_aggregate {consensus_content; committee}); + } + let seed_nonce_revelation_case = Case { @@ -1594,6 +1616,7 @@ module Encoding = struct let contents_cases_common = [ PCase attestations_aggregate_case; + PCase preattestations_aggregate_case; PCase double_preattestation_evidence_case; PCase double_attestation_evidence_case; PCase seed_nonce_revelation_case; diff --git a/src/proto_alpha/lib_protocol/operation_repr.mli b/src/proto_alpha/lib_protocol/operation_repr.mli index 4257e2dba6f6..538263618959 100644 --- a/src/proto_alpha/lib_protocol/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/operation_repr.mli @@ -756,6 +756,8 @@ module Encoding : sig val attestations_aggregate_case : Kind.attestations_aggregate case + val preattestations_aggregate_case : Kind.preattestations_aggregate case + val seed_nonce_revelation_case : Kind.seed_nonce_revelation case val vdf_revelation_case : Kind.vdf_revelation case -- GitLab From a1068960b9a5c7a878078b915e62a4d1654f13c5 Mon Sep 17 00:00:00 2001 From: Adam Allombert-Goget Date: Wed, 9 Apr 2025 16:35:10 +0200 Subject: [PATCH 3/3] kaitai: make check-kaitai-struct-files --- .../kaitai-struct-files/files/alpha__operation.ksy | 10 ++++++++++ .../files/alpha__operation__bls_mode_unsigned.ksy | 10 ++++++++++ .../files/alpha__operation__contents.ksy | 10 ++++++++++ .../files/alpha__operation__contents_list.ksy | 10 ++++++++++ .../files/alpha__operation__protocol_data.ksy | 10 ++++++++++ .../files/alpha__operation__unsigned.ksy | 10 ++++++++++ 6 files changed, 60 insertions(+) diff --git a/client-libs/kaitai-struct-files/files/alpha__operation.ksy b/client-libs/kaitai-struct-files/files/alpha__operation.ksy index 8e1576737d42..9f6640648209 100644 --- a/client-libs/kaitai-struct-files/files/alpha__operation.ksy +++ b/client-libs/kaitai-struct-files/files/alpha__operation.ksy @@ -148,6 +148,9 @@ types: - id: attestations_aggregate type: attestations_aggregate if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::attestations_aggregate) + - id: preattestations_aggregate + type: preattestations_aggregate + if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::preattestations_aggregate) - 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) @@ -899,6 +902,12 @@ types: type: s4be - id: block_payload_hash size: 32 + preattestations_aggregate: + seq: + - id: consensus_content + type: consensus_content + - id: committee + type: committee_0 price: seq: - id: id @@ -2030,6 +2039,7 @@ enums: 21: attestation 23: attestation_with_dal 24: dal_entrapment_evidence + 30: preattestations_aggregate 31: attestations_aggregate 107: reveal 108: transaction diff --git a/client-libs/kaitai-struct-files/files/alpha__operation__bls_mode_unsigned.ksy b/client-libs/kaitai-struct-files/files/alpha__operation__bls_mode_unsigned.ksy index 47e569bfda19..4a5550565793 100644 --- a/client-libs/kaitai-struct-files/files/alpha__operation__bls_mode_unsigned.ksy +++ b/client-libs/kaitai-struct-files/files/alpha__operation__bls_mode_unsigned.ksy @@ -134,6 +134,9 @@ types: - id: attestations_aggregate type: attestations_aggregate if: (alpha__operation__alpha__bls_mode_contents_tag == alpha__operation__alpha__bls_mode_contents_tag::attestations_aggregate) + - id: preattestations_aggregate + type: preattestations_aggregate + if: (alpha__operation__alpha__bls_mode_contents_tag == alpha__operation__alpha__bls_mode_contents_tag::preattestations_aggregate) - id: double_preattestation_evidence type: double_preattestation_evidence if: (alpha__operation__alpha__bls_mode_contents_tag == alpha__operation__alpha__bls_mode_contents_tag::double_preattestation_evidence) @@ -906,6 +909,12 @@ types: type: s4be - id: block_payload_hash size: 32 + preattestations_aggregate: + seq: + - id: consensus_content + type: consensus_content + - id: committee + type: committee_0 price: seq: - id: id @@ -2034,6 +2043,7 @@ enums: 9: drain_delegate 17: failing_noop 24: dal_entrapment_evidence + 30: preattestations_aggregate 31: attestations_aggregate 40: bls_mode_preattestation 41: bls_mode_attestation diff --git a/client-libs/kaitai-struct-files/files/alpha__operation__contents.ksy b/client-libs/kaitai-struct-files/files/alpha__operation__contents.ksy index 533fd67c91a2..28bc8c0b027c 100644 --- a/client-libs/kaitai-struct-files/files/alpha__operation__contents.ksy +++ b/client-libs/kaitai-struct-files/files/alpha__operation__contents.ksy @@ -137,6 +137,9 @@ types: - id: attestations_aggregate type: attestations_aggregate if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::attestations_aggregate) + - id: preattestations_aggregate + type: preattestations_aggregate + if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::preattestations_aggregate) - id: double_preattestation_evidence type: double_preattestation_evidence if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::double_preattestation_evidence) @@ -876,6 +879,12 @@ types: type: s4be - id: block_payload_hash size: 32 + preattestations_aggregate: + seq: + - id: consensus_content + type: consensus_content + - id: committee + type: committee_0 price: seq: - id: id @@ -2007,6 +2016,7 @@ enums: 21: attestation 23: attestation_with_dal 24: dal_entrapment_evidence + 30: preattestations_aggregate 31: attestations_aggregate 107: reveal 108: transaction diff --git a/client-libs/kaitai-struct-files/files/alpha__operation__contents_list.ksy b/client-libs/kaitai-struct-files/files/alpha__operation__contents_list.ksy index 476a78d54d70..66d84ed954f3 100644 --- a/client-libs/kaitai-struct-files/files/alpha__operation__contents_list.ksy +++ b/client-libs/kaitai-struct-files/files/alpha__operation__contents_list.ksy @@ -137,6 +137,9 @@ types: - id: attestations_aggregate type: attestations_aggregate if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::attestations_aggregate) + - id: preattestations_aggregate + type: preattestations_aggregate + if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::preattestations_aggregate) - id: double_preattestation_evidence type: double_preattestation_evidence if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::double_preattestation_evidence) @@ -880,6 +883,12 @@ types: type: s4be - id: block_payload_hash size: 32 + preattestations_aggregate: + seq: + - id: consensus_content + type: consensus_content + - id: committee + type: committee_0 price: seq: - id: id @@ -2011,6 +2020,7 @@ enums: 21: attestation 23: attestation_with_dal 24: dal_entrapment_evidence + 30: preattestations_aggregate 31: attestations_aggregate 107: reveal 108: transaction diff --git a/client-libs/kaitai-struct-files/files/alpha__operation__protocol_data.ksy b/client-libs/kaitai-struct-files/files/alpha__operation__protocol_data.ksy index 41fdb4524195..63c7638002ba 100644 --- a/client-libs/kaitai-struct-files/files/alpha__operation__protocol_data.ksy +++ b/client-libs/kaitai-struct-files/files/alpha__operation__protocol_data.ksy @@ -148,6 +148,9 @@ types: - id: attestations_aggregate type: attestations_aggregate if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::attestations_aggregate) + - id: preattestations_aggregate + type: preattestations_aggregate + if: (alpha__operation__alpha__contents_or_signature_prefix_tag == alpha__operation__alpha__contents_or_signature_prefix_tag::preattestations_aggregate) - 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) @@ -899,6 +902,12 @@ types: type: s4be - id: block_payload_hash size: 32 + preattestations_aggregate: + seq: + - id: consensus_content + type: consensus_content + - id: committee + type: committee_0 price: seq: - id: id @@ -2030,6 +2039,7 @@ enums: 21: attestation 23: attestation_with_dal 24: dal_entrapment_evidence + 30: preattestations_aggregate 31: attestations_aggregate 107: reveal 108: transaction diff --git a/client-libs/kaitai-struct-files/files/alpha__operation__unsigned.ksy b/client-libs/kaitai-struct-files/files/alpha__operation__unsigned.ksy index 803251b21c2f..f6125dbda13a 100644 --- a/client-libs/kaitai-struct-files/files/alpha__operation__unsigned.ksy +++ b/client-libs/kaitai-struct-files/files/alpha__operation__unsigned.ksy @@ -137,6 +137,9 @@ types: - id: attestations_aggregate type: attestations_aggregate if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::attestations_aggregate) + - id: preattestations_aggregate + type: preattestations_aggregate + if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::preattestations_aggregate) - id: double_preattestation_evidence type: double_preattestation_evidence if: (alpha__operation__alpha__contents_tag == alpha__operation__alpha__contents_tag::double_preattestation_evidence) @@ -887,6 +890,12 @@ types: type: s4be - id: block_payload_hash size: 32 + preattestations_aggregate: + seq: + - id: consensus_content + type: consensus_content + - id: committee + type: committee_0 price: seq: - id: id @@ -2018,6 +2027,7 @@ enums: 21: attestation 23: attestation_with_dal 24: dal_entrapment_evidence + 30: preattestations_aggregate 31: attestations_aggregate 107: reveal 108: transaction -- GitLab