diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index 371639d2003f88219c6741bdae11410621bfe8a3..636eb4866337b17bea48e90d3dbe155f8afa210a 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -102,6 +102,9 @@ Minor Changes - Allow ``finalise_unstake`` to be performed by any account (:gl:`!17950`). This allows finalisation of unstake requests to be done automatically by a third party - for example a finalisation bot. +- Consensus operations with different slots are no longer considered a + punishable misbehaviour (MR :gl:`!18043`) + Internal -------- 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 629363456ea9d8dff3ba20ef3a25b6c18dde114b..807f2ec9cb3343d228bb3f1b81816b653fc71112 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 @@ -250,7 +250,7 @@ let test_different_branch () = let* _blk = Block.bake ~operation blk in return_unit -(** Check that a double (pre)attestation evidence succeeds when the +(** Check that a double (pre)attestation evidence fails when the operations have distinct slots (that both belong to the delegate) and are otherwise identical. *) let test_different_slots () = @@ -279,30 +279,19 @@ let test_different_slots () = let double_preattestation = double_preattestation (B blk) preattestation1 preattestation2 in - let* {parametric = {aggregate_attestation; _}; _} = - Context.get_constants (B genesis) + let*! res = Block.bake ~operation:double_attestation blk in + let* () = + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_denunciation _ -> true + | _ -> false) in - (* Under [aggregate_attestation] feature flag, consensus operations with - non-minimal slots are not propagated by mempools and can't be denounced - anymore. *) - if aggregate_attestation then - let*! res = Block.bake ~operation:double_attestation blk in - let* () = - Assert.proto_error ~loc:__LOC__ res (function - | Validate_errors.Anonymous.Invalid_denunciation _ -> true - | _ -> false) - in - let*! res = Block.bake ~operation:double_preattestation blk in - let* () = - Assert.proto_error ~loc:__LOC__ res (function - | Validate_errors.Anonymous.Invalid_denunciation _ -> true - | _ -> false) - in - return_unit - else - let* (_ : Block.t) = Block.bake ~operation:double_attestation blk in - let* (_ : Block.t) = Block.bake ~operation:double_preattestation blk in - return_unit + let*! res = Block.bake ~operation:double_preattestation blk in + let* () = + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Anonymous.Invalid_denunciation _ -> true + | _ -> false) + in + return_unit (** Say a delegate double-attests twice and say the 2 evidences are timely included. Then the delegate can no longer bake. *) diff --git a/src/proto_alpha/lib_protocol/validate.ml b/src/proto_alpha/lib_protocol/validate.ml index 2adb9d2178c502cabbcbb3156a1fe2ea78a7165f..3523c7e1de131305e82da8cd202ff1a4bfe47d03 100644 --- a/src/proto_alpha/lib_protocol/validate.ml +++ b/src/proto_alpha/lib_protocol/validate.ml @@ -1948,36 +1948,19 @@ module Anonymous = struct Block_payload_hash.(e1.block_payload_hash = e2.block_payload_hash) in let same_branches = Block_hash.(op1.shell.branch = op2.shell.branch) in - let same_slots = Slot.(e1.slot = e2.slot) in let ordered_hashes = Operation_hash.(op1_hash < op2_hash) in - (* consensus operations with different slots are not slashed when - aggregate_attestation feature flag is enabled. *) - let aggregate_attestation_feature_flag = - Constants.aggregate_attestation vi.ctxt - in - let is_slot_denunciable = - match kind with - | Misbehaviour.(Double_attesting | Double_preattesting) -> - not aggregate_attestation_feature_flag - | _ -> true - in let is_denunciation_consistent = same_levels && same_rounds - (* For the double (pre)attestations to be punishable, they - must point to the same block (same level and round), but - also have at least a difference that is the delegate's - fault: different payloads, different branches, or - different slots. Note that different payloads would - endanger the consensus process, while different branches - or slots could be used to spam mempools with a lot of - valid operations (since the minimality of the slot in not - checked in mempool mode, only in block-related modes). On - the other hand, if the operations have identical levels, - rounds, payloads, branches, and slots, then only their - signatures are different, which is not considered the - delegate's fault and therefore is not punished. *) - && ((not same_payload) || (not same_branches) - || ((not same_slots) && is_slot_denunciable)) + (* For the double (pre)attestations to be punishable, they must point to + the same block (same level and round), but also have at least a + difference that is the delegate's fault: different payloads or + different branches. Note that different payloads would endanger the + consensus process, while different branches could be used to spam + mempools with a lot of valid operations. On the other hand, if the + operations have identical levels, rounds, payloads, branches, and + slots, then only their signatures are different, which is not + considered the delegate's fault and therefore is not punished. *) + && ((not same_payload) || not same_branches) && (* we require an order on hashes to avoid the existence of equivalent evidences *) ordered_hashes