From a6c18fec9dd0969b94b9bc668cacfe55f98af81c Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 21 May 2025 18:26:17 +0200 Subject: [PATCH 1/2] Proto: update receipts for denunciations --- .../lib_client/operation_result.ml | 46 ++++++-------- .../lib_protocol/alpha_context.mli | 6 ++ src/proto_alpha/lib_protocol/apply.ml | 62 ++++++++++--------- src/proto_alpha/lib_protocol/apply_results.ml | 57 +++++++++-------- .../lib_protocol/apply_results.mli | 18 +++--- .../lib_protocol/misbehaviour_repr.ml | 19 ++++++ .../lib_protocol/misbehaviour_repr.mli | 4 ++ .../lib_protocol/test/helpers/block.ml | 9 ++- .../consensus/test_double_attestation.ml | 4 +- 9 files changed, 130 insertions(+), 95 deletions(-) diff --git a/src/proto_alpha/lib_client/operation_result.ml b/src/proto_alpha/lib_client/operation_result.ml index 0fc82b01eca5..b3b64470f02b 100644 --- a/src/proto_alpha/lib_client/operation_result.ml +++ b/src/proto_alpha/lib_client/operation_result.ml @@ -959,15 +959,17 @@ let pp_manager_operation_result ppf let pp_contents_and_result : type kind. Format.formatter -> kind contents * kind contents_result -> unit = - let pp_forbidden ppf forbidden = - match forbidden with - | None -> () - | Some forbidden_delegate -> - Format.fprintf - ppf - " Forbidden delegate: %a@," - Signature.Public_key_hash.pp - forbidden_delegate + let pp_double_signing_result ppf + {punished_delegate; rewarded_delegate; misbehaviour} = + Format.fprintf + ppf + "Misbehaviour: %a@,Punished delegate: %a@,Rewarded delegate: %a" + Misbehaviour.pp + misbehaviour + Signature.Public_key_hash.pp + punished_delegate + Signature.Public_key_hash.pp + rewarded_delegate in fun ppf -> function | Seed_nonce_revelation {level; nonce}, Seed_nonce_revelation_result bus -> @@ -993,22 +995,16 @@ let pp_contents_and_result : pp_balance_updates bus | ( Double_baking_evidence {bh1; bh2}, - Double_baking_evidence_result {forbidden_delegate; balance_updates} ) -> + Double_baking_evidence_result double_signing_result ) -> Format.fprintf ppf - "@[Double baking evidence:@,\ - Exhibit A: %a@,\ - Exhibit B: %a@,\ - %aBalance updates:@,\ - %a@]" + "@[Double baking evidence:@,Exhibit A: %a@,Exhibit B: %a@,%a@]" Block_hash.pp (Block_header.hash bh1) Block_hash.pp (Block_header.hash bh2) - pp_forbidden - forbidden_delegate - pp_balance_updates - balance_updates + pp_double_signing_result + double_signing_result | ( Preattestation {level; _}, Preattestation_result {balance_updates; delegate; consensus_key; consensus_power} ) -> @@ -1078,26 +1074,22 @@ let pp_contents_and_result : committee consensus_power | ( Double_consensus_operation_evidence {slot; op1; op2}, - Double_consensus_operation_evidence_result - {forbidden_delegate; balance_updates} ) -> + Double_consensus_operation_evidence_result double_signing_result ) -> Format.fprintf ppf "@[Double consensus operation evidence:@,\ Slot: %a@,\ Exhibit A: %a@,\ Exhibit B: %a@,\ - %aBalance updates:@,\ - \ %a@]" + %a@]" Slot.pp slot Operation_hash.pp (Operation.hash op1) Operation_hash.pp (Operation.hash op2) - pp_forbidden - forbidden_delegate - pp_balance_updates - balance_updates + pp_double_signing_result + double_signing_result | ( Dal_entrapment_evidence { attestation; diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 12d5a33e59c5..d612491fee77 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2264,8 +2264,14 @@ module Misbehaviour : sig type t = {level : Raw_level.t; round : Round.t; kind : kind} + val pp_kind : Format.formatter -> kind -> unit + + val pp : Format.formatter -> t -> unit + val kind_encoding : kind Data_encoding.t + val encoding : t Data_encoding.t + val compare_kind : kind -> kind -> int val equal_kind : kind -> kind -> bool diff --git a/src/proto_alpha/lib_protocol/apply.ml b/src/proto_alpha/lib_protocol/apply.ml index 3442a2af0e35..8a492d9c5f16 100644 --- a/src/proto_alpha/lib_protocol/apply.ml +++ b/src/proto_alpha/lib_protocol/apply.ml @@ -2488,10 +2488,10 @@ let apply_manager_operations ctxt ~payload_producer chain_id ~mempool_mode in return (ctxt, contents_result_list) -let punish_delegate ctxt ~operation_hash delegate level misbehaviour mk_result +let punish_double_signing ctxt ~operation_hash delegate level misbehaviour ~payload_producer = let open Lwt_result_syntax in - let rewarded = payload_producer.Consensus_key.delegate in + let rewarded_delegate = payload_producer.Consensus_key.delegate in let* ctxt = Delegate.punish_double_signing ctxt @@ -2499,10 +2499,12 @@ let punish_delegate ctxt ~operation_hash delegate level misbehaviour mk_result misbehaviour delegate level - ~rewarded + ~rewarded:rewarded_delegate in - let content_result = mk_result (Some delegate) [] in - return (ctxt, Single_result content_result) + let contents_result = + {punished_delegate = delegate; rewarded_delegate; misbehaviour} + in + return (ctxt, contents_result) let punish_double_consensus_operation (type kind) ctxt ~operation_hash ~payload_producer contents = @@ -2520,40 +2522,42 @@ let punish_double_consensus_operation (type kind) ctxt ~operation_hash | Attestations_aggregate {consensus_content = {level; round; _}; _} ) -> Misbehaviour.{level; round; kind = Double_attesting} in - let mk_result forbidden_delegate balance_updates = - Double_consensus_operation_evidence_result - {forbidden_delegate; balance_updates} - in let level = Level.from_raw ctxt misbehaviour.level in let* ctxt, {delegate; _} = Stake_distribution.slot_owner ctxt level slot in - punish_delegate - ctxt - ~operation_hash - delegate - level - misbehaviour - mk_result - ~payload_producer + let* ctxt, contents_result = + punish_double_signing + ctxt + ~operation_hash + delegate + level + misbehaviour + ~payload_producer + in + return + ( ctxt, + Single_result (Double_consensus_operation_evidence_result contents_result) + ) let punish_double_baking ctxt ~operation_hash (bh1 : Block_header.t) ~payload_producer = let open Lwt_result_syntax in let*? bh1_fitness = Fitness.from_raw bh1.shell.fitness in - let round1 = Fitness.round bh1_fitness in + let round = Fitness.round bh1_fitness in let*? raw_level = Raw_level.of_int32 bh1.shell.level in let level = Level.from_raw ctxt raw_level in - let* ctxt, _, consensus_pk1 = - Stake_distribution.baking_rights_owner ctxt level ~round:round1 + let* ctxt, _, {delegate; _} = + Stake_distribution.baking_rights_owner ctxt level ~round in - punish_delegate - ctxt - ~operation_hash - consensus_pk1.delegate - level - {level = raw_level; round = round1; kind = Double_baking} - ~payload_producer - (fun forbidden_delegate balance_updates -> - Double_baking_evidence_result {forbidden_delegate; balance_updates}) + let* ctxt, contents_result = + punish_double_signing + ctxt + ~operation_hash + delegate + level + {level = raw_level; round; kind = Double_baking} + ~payload_producer + in + return (ctxt, Single_result (Double_baking_evidence_result contents_result)) let apply_contents_list (type kind) ctxt chain_id (mode : mode) ~payload_producer ~operation ~operation_hash diff --git a/src/proto_alpha/lib_protocol/apply_results.ml b/src/proto_alpha/lib_protocol/apply_results.ml index ebed1fdefd26..1a8a398ccf06 100644 --- a/src/proto_alpha/lib_protocol/apply_results.ml +++ b/src/proto_alpha/lib_protocol/apply_results.ml @@ -877,6 +877,12 @@ let successful_manager_operation_result_encoding : make Manager_result.sc_rollup_originate_case; ] +type double_signing_result = { + punished_delegate : public_key_hash; + rewarded_delegate : public_key_hash; + misbehaviour : Misbehaviour.t; +} + type 'kind contents_result = | Preattestation_result : { balance_updates : Receipt.balance_updates; @@ -910,15 +916,11 @@ type 'kind contents_result = | Vdf_revelation_result : Receipt.balance_updates -> Kind.vdf_revelation contents_result - | Double_consensus_operation_evidence_result : { - forbidden_delegate : Signature.public_key_hash option; - balance_updates : Receipt.balance_updates; - } + | Double_consensus_operation_evidence_result : + double_signing_result -> Kind.double_consensus_operation_evidence contents_result - | Double_baking_evidence_result : { - forbidden_delegate : Signature.public_key_hash option; - balance_updates : Receipt.balance_updates; - } + | Double_baking_evidence_result : + double_signing_result -> Kind.double_baking_evidence contents_result | Dal_entrapment_evidence_result : { balance_updates : Receipt.balance_updates; @@ -1227,14 +1229,22 @@ module Encoding = struct inj = (fun bus -> Vdf_revelation_result bus); } + let double_signing_result_encoding = + conv + (fun {punished_delegate; rewarded_delegate; misbehaviour} -> + (punished_delegate, rewarded_delegate, misbehaviour)) + (fun (punished_delegate, rewarded_delegate, misbehaviour) -> + {punished_delegate; rewarded_delegate; misbehaviour}) + (obj3 + (req "punished_delegate" Signature.Public_key_hash.encoding) + (req "rewarded_delegate" Signature.Public_key_hash.encoding) + (req "misbehaviour" Misbehaviour.encoding)) + let double_consensus_operation_evidence_case = Case { op_case = Operation.Encoding.double_consensus_operation_evidence_case; - encoding = - obj2 - (opt "forbidden_delegate" Signature.Public_key_hash.encoding) - (dft "balance_updates" Receipt.balance_updates_encoding []); + encoding = double_signing_result_encoding; select = (function | Contents_result (Double_consensus_operation_evidence_result _ as op) @@ -1249,22 +1259,18 @@ module Encoding = struct | _ -> None); proj = (fun (Double_consensus_operation_evidence_result - {forbidden_delegate; balance_updates}) -> - (forbidden_delegate, balance_updates)); + double_signing_result) -> + double_signing_result); inj = - (fun (forbidden_delegate, balance_updates) -> - Double_consensus_operation_evidence_result - {forbidden_delegate; balance_updates}); + (fun double_signing_result -> + Double_consensus_operation_evidence_result double_signing_result); } let double_baking_evidence_case = Case { op_case = Operation.Encoding.double_baking_evidence_case; - encoding = - obj2 - (opt "forbidden_delegate" Signature.Public_key_hash.encoding) - (dft "balance_updates" Receipt.balance_updates_encoding []); + encoding = double_signing_result_encoding; select = (function | Contents_result (Double_baking_evidence_result _ as op) -> Some op @@ -1275,12 +1281,11 @@ module Encoding = struct Some (op, res) | _ -> None); proj = - (fun (Double_baking_evidence_result - {forbidden_delegate; balance_updates}) -> - (forbidden_delegate, balance_updates)); + (fun (Double_baking_evidence_result double_signing_result) -> + double_signing_result); inj = - (fun (forbidden_delegate, balance_updates) -> - Double_baking_evidence_result {forbidden_delegate; balance_updates}); + (fun double_signing_result -> + Double_baking_evidence_result double_signing_result); } let dal_entrapment_evidence_case = diff --git a/src/proto_alpha/lib_protocol/apply_results.mli b/src/proto_alpha/lib_protocol/apply_results.mli index 52b29c03b4dc..21434b291695 100644 --- a/src/proto_alpha/lib_protocol/apply_results.mli +++ b/src/proto_alpha/lib_protocol/apply_results.mli @@ -37,6 +37,12 @@ open Alpha_context open Apply_operation_result open Apply_internal_results +type double_signing_result = { + punished_delegate : public_key_hash; + rewarded_delegate : public_key_hash; + misbehaviour : Misbehaviour.t; +} + (** Result of applying a {!Operation.t}. Follows the same structure. *) type 'kind operation_metadata = {contents : 'kind contents_result_list} @@ -91,15 +97,11 @@ and 'kind contents_result = | Vdf_revelation_result : Receipt.balance_updates -> Kind.vdf_revelation contents_result - | Double_consensus_operation_evidence_result : { - forbidden_delegate : Signature.public_key_hash option; - balance_updates : Receipt.balance_updates; - } + | Double_consensus_operation_evidence_result : + double_signing_result -> Kind.double_consensus_operation_evidence contents_result - | Double_baking_evidence_result : { - forbidden_delegate : Signature.public_key_hash option; - balance_updates : Receipt.balance_updates; - } + | Double_baking_evidence_result : + double_signing_result -> Kind.double_baking_evidence contents_result | Dal_entrapment_evidence_result : { balance_updates : Receipt.balance_updates; diff --git a/src/proto_alpha/lib_protocol/misbehaviour_repr.ml b/src/proto_alpha/lib_protocol/misbehaviour_repr.ml index a2a57ace6416..b1ee48e13753 100644 --- a/src/proto_alpha/lib_protocol/misbehaviour_repr.ml +++ b/src/proto_alpha/lib_protocol/misbehaviour_repr.ml @@ -18,6 +18,25 @@ let kind_encoding = type t = {level : Raw_level_repr.t; round : Round_repr.t; kind : kind} +let pp_kind fmt kind = + Format.pp_print_string + fmt + (match kind with + | Double_baking -> "double-baking" + | Double_attesting -> "double-attesting" + | Double_preattesting -> "double-preattesting") + +let pp fmt {level; round; kind} = + Format.fprintf + fmt + "%a at level %a, round %a" + pp_kind + kind + Raw_level_repr.pp + level + Round_repr.pp + round + let compare_kind a b = let to_int = function | Double_baking -> 0 diff --git a/src/proto_alpha/lib_protocol/misbehaviour_repr.mli b/src/proto_alpha/lib_protocol/misbehaviour_repr.mli index d7dd11a5b7fe..b8cf097b7952 100644 --- a/src/proto_alpha/lib_protocol/misbehaviour_repr.mli +++ b/src/proto_alpha/lib_protocol/misbehaviour_repr.mli @@ -22,6 +22,10 @@ type kind = Double_baking | Double_attesting | Double_preattesting context. *) type t = {level : Raw_level_repr.t; round : Round_repr.t; kind : kind} +val pp_kind : Format.formatter -> kind -> unit + +val pp : Format.formatter -> t -> unit + val kind_encoding : kind Data_encoding.t val encoding : t Data_encoding.t diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 2a04bea46b27..052ca8d58d6e 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -1165,15 +1165,18 @@ let balance_updates_of_single_content : type a. a Protocol.Apply_results.contents_result -> Protocol.Alpha_context.Receipt.balance_updates = function - | Proposals_result | Ballot_result -> [] + | Proposals_result | Ballot_result + | Double_consensus_operation_evidence_result + {punished_delegate = _; rewarded_delegate = _; misbehaviour = _} + | Double_baking_evidence_result + {punished_delegate = _; rewarded_delegate = _; misbehaviour = _} -> + [] | 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 - | Double_consensus_operation_evidence_result {balance_updates; _} - | Double_baking_evidence_result {balance_updates; _} | Dal_entrapment_evidence_result {balance_updates; _} | Activate_account_result balance_updates | Drain_delegate_result {balance_updates; _} -> diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_attestation.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_attestation.ml index b9c6037fc415..6b56a645a9b2 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_attestation.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_attestation.ml @@ -342,9 +342,9 @@ let test_two_double_attestation_evidences_leadsto_no_bake () = contents = Apply_results.Single_result (Apply_results.Double_consensus_operation_evidence_result - rslt); + {punished_delegate; _}); } -> - rslt.forbidden_delegate = Some delegate + Signature.Public_key_hash.(punished_delegate = delegate) | _ -> false) operations_recpts in -- GitLab From fdd2cdd763d0a5e21dd39a172bddb8786ac98005 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Thu, 22 May 2025 12:16:20 +0200 Subject: [PATCH 2/2] Changelog: entry on denunciation receipts --- docs/protocols/alpha.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index c3b4c0b94af7..e2faffb41dd7 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -108,6 +108,24 @@ Operation receipts key update, with the ``kind`` field used to differientiate between both. (MR :gl:`!17320`) +- Reworked the receipts for the + ``Double_consensus_operation_evidence`` and + ``Double_baking_evidence`` operations (MR :gl:`!18103`): + + - The ``balance_updates`` field has been removed, because these + operations no longer produce them since the Oxford protocol. + + - The ``forbidden_delegate`` field has been renamed to + ``punished_delegate`` and is no longer optional, because + forbidding the punished delegate has been systematic since the + Paris protocol. + + - A new ``rewarded_delegate`` field has been added, because it's no + longer easily retrievable from the balance updates since Oxford. + + - A new ``misbehaviour`` field has been added, containing the + misbehaviour's level, round, and kind + (double-baking/double-attesting/double-preattesting). Errors ------ -- GitLab