From 515e34e105e78a7681b6a428c9f542030758a38c Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Mon, 27 Feb 2023 18:29:13 +0100 Subject: [PATCH 01/10] Proto/test: rework test_consensus_operation arguments --- .../test/helpers/consensus_helpers.ml | 59 +++++++++++++------ .../integration/consensus/test_endorsement.ml | 46 +++++++-------- .../consensus/test_preendorsement.ml | 34 +++++------ 3 files changed, 75 insertions(+), 64 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml index 3db4a7d1ab13..5a16c17aa318 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml @@ -26,25 +26,48 @@ open Protocol open Alpha_context -let test_consensus_operation ?construction_mode ?level ?block_payload_hash ?slot - ?round ~endorsed_block ~error ~is_preendorsement ~loc () = - (if is_preendorsement then - Op.preendorsement ?block_payload_hash ?level ?slot ?round endorsed_block - else Op.endorsement ?block_payload_hash ?level ?slot ?round endorsed_block) - >>=? fun operation -> +type mode = Application | Construction | Mempool + +type kind = Preendorsement | Endorsement + +(** Craft an endorsement or preendorsement, and bake a block + containing it (in application or construction modes) or inject it + into a mempool. Check that it fails as specified by [error]. + + By default, the (pre)endorsement is for the first slot and is + signed by the delegate that owns this slot. Moreover, the operation + points to the given [endorsed_block]: in other words, it has that + block's level, round, payload hash, and its branch is the + predecessor of that block. Optional arguments allow to override + these default parameters. + + The [endorsed_block] is also used as the predecessor of the baked + block, or as the head of the mempool. *) +let test_consensus_operation ?slot ?level ?round ?block_payload_hash + ~endorsed_block ~error ~loc kind mode = + let open Lwt_result_syntax in + let* operation = + match kind with + | Preendorsement -> + Op.preendorsement ?slot ?level ?round ?block_payload_hash endorsed_block + | Endorsement -> + Op.endorsement ?slot ?level ?round ?block_payload_hash endorsed_block + in let assert_error res = Assert.proto_error ~loc res error in - match construction_mode with - | None -> - (* meaning Application mode *) - Block.bake ~operation endorsed_block >>= assert_error - | Some (pred, protocol_data) -> - (* meaning partial construction or full construction mode, depending on - [protocol_data] *) - Block.get_construction_vstate ~protocol_data pred - >>=? fun (validation_state, _application_state) -> - let oph = Operation.hash_packed operation in - validate_operation validation_state oph operation - >|= Environment.wrap_tzresult >>= assert_error + match mode with + | Application -> + Block.bake ~baking_mode:Application ~operation endorsed_block + >>= assert_error + | Construction -> + Block.bake ~baking_mode:Baking ~operation endorsed_block >>= assert_error + | Mempool -> + let*! res = + let* inc = + Incremental.begin_construction ~mempool_mode:true endorsed_block + in + Incremental.validate_operation inc operation + in + assert_error res let delegate_of_first_slot b = let module V = Plugin.RPC.Validators in diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index 549f19572291..cd7e89403d18 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -162,7 +162,6 @@ let test_consensus_operation_endorsement_for_future_level () = let level = match raw_level with Ok l -> l | Error _ -> assert false in Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:pred ~level ~error:(function @@ -170,8 +169,8 @@ let test_consensus_operation_endorsement_for_future_level () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Endorsement + Mempool (** Consensus operation for old level : apply an endorsement one level in the past *) let test_consensus_operation_endorsement_for_predecessor_level () = @@ -180,7 +179,6 @@ let test_consensus_operation_endorsement_for_predecessor_level () = let level = match raw_level with Ok l -> l | Error _ -> assert false in Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:pred ~level ~error:(function @@ -188,8 +186,8 @@ let test_consensus_operation_endorsement_for_predecessor_level () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Endorsement + Mempool (** Consensus operation for old level : apply an endorsement with more than one level in the past *) let test_consensus_operation_endorsement_for_old_level () = @@ -199,7 +197,6 @@ let test_consensus_operation_endorsement_for_old_level () = let level = match raw_level with Ok l -> l | Error _ -> assert false in Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:pred ~level ~error:(function @@ -207,8 +204,8 @@ let test_consensus_operation_endorsement_for_old_level () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Endorsement + Mempool (** Consensus operation for future round : apply an endorsement with a round in the future *) let test_consensus_operation_endorsement_for_future_round () = @@ -216,7 +213,6 @@ let test_consensus_operation_endorsement_for_future_round () = Environment.wrap_tzresult (Round.of_int 21) >>?= fun round -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:pred ~round ~error:(function @@ -224,8 +220,8 @@ let test_consensus_operation_endorsement_for_future_round () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Endorsement + Mempool (** Consensus operation for old round : apply an endorsement with a round in the past *) let test_consensus_operation_endorsement_for_old_round () = @@ -233,7 +229,6 @@ let test_consensus_operation_endorsement_for_old_round () = Environment.wrap_tzresult (Round.of_int 0) >>?= fun round -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:pred ~round ~error:(function @@ -241,15 +236,14 @@ let test_consensus_operation_endorsement_for_old_round () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Endorsement + Mempool (** Consensus operation on competing proposal : apply an endorsement on a competing proposal *) let test_consensus_operation_endorsement_on_competing_proposal () = init_genesis () >>=? fun (_genesis, pred) -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:pred ~block_payload_hash:Block_payload_hash.zero ~error:(function @@ -258,8 +252,8 @@ let test_consensus_operation_endorsement_on_competing_proposal () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Endorsement + Mempool (** Wrong round : apply an endorsement with an incorrect round *) let test_wrong_round () = @@ -267,7 +261,6 @@ let test_wrong_round () = Environment.wrap_tzresult (Round.of_int 2) >>?= fun round -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:b ~round ~error:(function @@ -275,7 +268,8 @@ let test_wrong_round () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - () + Endorsement + Application (** Wrong level : apply an endorsement with an incorrect level *) let test_wrong_level () = @@ -285,7 +279,6 @@ let test_wrong_level () = let level = match raw_level with Ok l -> l | Error _ -> assert false in Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:b ~level ~error:(function @@ -293,14 +286,14 @@ let test_wrong_level () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - () + Endorsement + Application (** Wrong payload hash : apply an endorsement with an incorrect payload hash *) let test_wrong_payload_hash () = init_genesis () >>=? fun (_genesis, b) -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:b ~block_payload_hash:Block_payload_hash.zero ~error:(function @@ -309,7 +302,8 @@ let test_wrong_payload_hash () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - () + Endorsement + Application let test_wrong_slot_used () = init_genesis () >>=? fun (_genesis, b) -> @@ -320,7 +314,6 @@ let test_wrong_slot_used () = >>=? fun slot -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:false ~endorsed_block:b ~slot ~error:(function @@ -329,7 +322,8 @@ let test_wrong_slot_used () = when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - () + Endorsement + Application (** Check that: - a block with not enough endorsement cannot be baked; diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement.ml index aab600a17130..9107b541ad0c 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement.ml @@ -62,7 +62,6 @@ let test_consensus_operation_preendorsement_for_future_level () = let level = match raw_level with Ok l -> l | Error _ -> assert false in Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:true ~endorsed_block:pred ~level ~error:(function @@ -70,8 +69,8 @@ let test_consensus_operation_preendorsement_for_future_level () = when kind = Validate_errors.Consensus.Preendorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Preendorsement + Mempool (** Consensus operation for old level : apply a preendorsement with a level in the past *) let test_consensus_operation_preendorsement_for_old_level () = @@ -80,7 +79,6 @@ let test_consensus_operation_preendorsement_for_old_level () = let level = match raw_level with Ok l -> l | Error _ -> assert false in Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:true ~endorsed_block:pred ~level ~error:(function @@ -88,8 +86,8 @@ let test_consensus_operation_preendorsement_for_old_level () = when kind = Validate_errors.Consensus.Preendorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Preendorsement + Mempool (** Consensus operation for future round : apply a preendorsement with a round in the future *) let test_consensus_operation_preendorsement_for_future_round () = @@ -97,7 +95,6 @@ let test_consensus_operation_preendorsement_for_future_round () = Environment.wrap_tzresult (Round.of_int 21) >>?= fun round -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:true ~endorsed_block:pred ~round ~error:(function @@ -105,8 +102,8 @@ let test_consensus_operation_preendorsement_for_future_round () = when kind = Validate_errors.Consensus.Preendorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Preendorsement + Mempool (** Consensus operation for old round : apply a preendorsement with a round in the past *) let test_consensus_operation_preendorsement_for_old_round () = @@ -114,7 +111,6 @@ let test_consensus_operation_preendorsement_for_old_round () = Environment.wrap_tzresult (Round.of_int 0) >>?= fun round -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:true ~endorsed_block:pred ~round ~error:(function @@ -122,15 +118,14 @@ let test_consensus_operation_preendorsement_for_old_round () = when kind = Validate_errors.Consensus.Preendorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Preendorsement + Mempool (** Consensus operation on competing proposal : apply a preendorsement on a competing proposal *) let test_consensus_operation_preendorsement_on_competing_proposal () = init_genesis () >>=? fun (_genesis, pred) -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:true ~endorsed_block:pred ~block_payload_hash:Block_payload_hash.zero ~error:(function @@ -139,20 +134,20 @@ let test_consensus_operation_preendorsement_on_competing_proposal () = when kind = Validate_errors.Consensus.Preendorsement -> true | _ -> false) - ~construction_mode:(pred, None) - () + Preendorsement + Mempool (** Unexpected preendorsements in block : apply a preendorsement with an incorrect round *) let test_unexpected_preendorsements_in_blocks () = init_genesis () >>=? fun (_genesis, pred) -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:true ~endorsed_block:pred ~error:(function | Validate_errors.Consensus.Unexpected_preendorsement_in_block -> true | _ -> false) - () + Preendorsement + Application (** Round too high : apply a preendorsement with a too high round *) let test_too_high_round () = @@ -162,15 +157,14 @@ let test_too_high_round () = Environment.wrap_tzresult (Round.of_int 1) >>?= fun round -> Consensus_helpers.test_consensus_operation ~loc:__LOC__ - ~is_preendorsement:true ~endorsed_block:pred ~round ~level ~error:(function | Validate_errors.Consensus.Preendorsement_round_too_high _ -> true | _ -> false) - ~construction_mode:(pred, Some pred.header.protocol_data) - () + Preendorsement + Construction (** Duplicate preendorsement : apply a preendorsement that has already been applied. *) let test_duplicate_preendorsement () = -- GitLab From c36d3622f208b410c87513b7a93e60cef87866c3 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 1 Mar 2023 14:05:14 +0100 Subject: [PATCH 02/10] Proto/test: rename pred_branch to branch now that it is not necessarily the predecessor hash --- .../lib_protocol/test/helpers/op.ml | 44 +++++++++---------- .../lib_protocol/test/helpers/op.mli | 15 ++++--- .../consensus/test_double_endorsement.ml | 4 +- .../integration/consensus/test_endorsement.ml | 2 +- .../consensus/test_preendorsement.ml | 2 +- .../consensus/test_preendorsement_functor.ml | 11 +---- 6 files changed, 35 insertions(+), 43 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index bb04d5fbb9b6..740157f2f264 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -54,11 +54,11 @@ let mk_block_payload_hash payload_round (b : Block.t) = ~payload_round hashes -let mk_consensus_content_signer_and_pred_branch ?delegate ?slot ?level ?round - ?block_payload_hash ?pred_branch endorsed_block = +let mk_consensus_content_signer_and_branch ?delegate ?slot ?level ?round + ?block_payload_hash ?branch endorsed_block = let open Lwt_result_syntax in - let pred_branch = - match pred_branch with + let branch = + match branch with | None -> endorsed_block.Block.header.shell.predecessor | Some branch -> branch in @@ -95,19 +95,19 @@ let mk_consensus_content_signer_and_pred_branch ?delegate ?slot ?level ?round in let consensus_content = {slot; level; round; block_payload_hash} in let* signer = Account.find delegate_pkh in - return (consensus_content, signer.sk, pred_branch) + return (consensus_content, signer.sk, branch) -let raw_endorsement ?delegate ?slot ?level ?round ?block_payload_hash - ?pred_branch endorsed_block = +let raw_endorsement ?delegate ?slot ?level ?round ?block_payload_hash ?branch + endorsed_block = let open Lwt_result_syntax in - let* consensus_content, signer, pred_branch = - mk_consensus_content_signer_and_pred_branch + let* consensus_content, signer, branch = + mk_consensus_content_signer_and_branch ?delegate ?slot ?level ?round ?block_payload_hash - ?pred_branch + ?branch endorsed_block in let op = Single (Endorsement consensus_content) in @@ -115,10 +115,10 @@ let raw_endorsement ?delegate ?slot ?level ?round ?block_payload_hash (sign ~watermark:Operation.(to_watermark (Endorsement Chain_id.zero)) signer - pred_branch + branch op) -let endorsement ?delegate ?slot ?level ?round ?block_payload_hash ?pred_branch +let endorsement ?delegate ?slot ?level ?round ?block_payload_hash ?branch endorsed_block = let open Lwt_result_syntax in let* op = @@ -128,22 +128,22 @@ let endorsement ?delegate ?slot ?level ?round ?block_payload_hash ?pred_branch ?level ?round ?block_payload_hash - ?pred_branch + ?branch endorsed_block in return (Operation.pack op) -let raw_preendorsement ?delegate ?slot ?level ?round ?block_payload_hash - ?pred_branch endorsed_block = +let raw_preendorsement ?delegate ?slot ?level ?round ?block_payload_hash ?branch + endorsed_block = let open Lwt_result_syntax in - let* consensus_content, signer, pred_branch = - mk_consensus_content_signer_and_pred_branch + let* consensus_content, signer, branch = + mk_consensus_content_signer_and_branch ?delegate ?slot ?level ?round ?block_payload_hash - ?pred_branch + ?branch endorsed_block in let op = Single (Preendorsement consensus_content) in @@ -151,11 +151,11 @@ let raw_preendorsement ?delegate ?slot ?level ?round ?block_payload_hash (sign ~watermark:Operation.(to_watermark (Preendorsement Chain_id.zero)) signer - pred_branch + branch op) -let preendorsement ?delegate ?slot ?level ?round ?block_payload_hash - ?pred_branch endorsed_block = +let preendorsement ?delegate ?slot ?level ?round ?block_payload_hash ?branch + endorsed_block = let open Lwt_result_syntax in let* op = raw_preendorsement @@ -164,7 +164,7 @@ let preendorsement ?delegate ?slot ?level ?round ?block_payload_hash ?level ?round ?block_payload_hash - ?pred_branch + ?branch endorsed_block in return (Operation.pack op) diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.mli b/src/proto_alpha/lib_protocol/test/helpers/op.mli index 09f4b988bb03..56158fc3572b 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/op.mli @@ -56,17 +56,18 @@ val sign : Optional parameters allow to specify the endorsed values: [level], [round] and/or [block_payload_hash]. - They also allow to specify the endorser, [delegate], and/or the - [slot]. + They also allow to specify the endorser ([delegate]), and/or the + [slot]. These default to the first slot and its delegate. - Finally, the predecessor branch, [pred_branch] can be specified.*) + Finally, the operation [branch] can be specified. It defaults to the + predecessor of the endorsed block. *) val raw_endorsement : ?delegate:public_key_hash -> ?slot:Slot.t -> ?level:Raw_level.t -> ?round:Round.t -> ?block_payload_hash:Block_payload_hash.t -> - ?pred_branch:Block_hash.t -> + ?branch:Block_hash.t -> Block.t -> Kind.endorsement Operation.t tzresult Lwt.t @@ -80,7 +81,7 @@ val raw_preendorsement : ?level:Raw_level.t -> ?round:Round.t -> ?block_payload_hash:Block_payload_hash.t -> - ?pred_branch:Block_hash.t -> + ?branch:Block_hash.t -> Block.t -> Kind.preendorsement Operation.t tzresult Lwt.t @@ -92,7 +93,7 @@ val endorsement : ?level:Raw_level.t -> ?round:Round.t -> ?block_payload_hash:Block_payload_hash.t -> - ?pred_branch:Block_hash.t -> + ?branch:Block_hash.t -> Block.t -> Operation.packed tzresult Lwt.t @@ -104,7 +105,7 @@ val preendorsement : ?level:Raw_level.t -> ?round:Round.t -> ?block_payload_hash:Block_payload_hash.t -> - ?pred_branch:Block_hash.t -> + ?branch:Block_hash.t -> Block.t -> Operation.packed tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_endorsement.ml index 911051eb3c36..9e5bc24de94e 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_double_endorsement.ml @@ -137,12 +137,12 @@ let test_different_branch () = Block.bake genesis >>=? fun blk -> Context.get_endorser (B blk) >>=? fun (endorser, _slots) -> Op.raw_endorsement ~delegate:endorser blk >>=? fun endorsement_a -> - Op.raw_endorsement ~pred_branch:Block_hash.zero ~delegate:endorser blk + Op.raw_endorsement ~branch:Block_hash.zero ~delegate:endorser blk >>=? fun endorsement_b -> let operation = double_endorsement (B blk) endorsement_a endorsement_b in Block.bake ~operation blk >>=? fun _blk -> Op.raw_preendorsement ~delegate:endorser blk >>=? fun preendorsement_a -> - Op.raw_preendorsement ~pred_branch:Block_hash.zero ~delegate:endorser blk + Op.raw_preendorsement ~branch:Block_hash.zero ~delegate:endorser blk >>=? fun preendorsement_b -> let operation = double_preendorsement (B blk) preendorsement_a preendorsement_b diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index cd7e89403d18..76cf06f5b13f 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -60,7 +60,7 @@ let test_simple_endorsement () = validity. *) let test_endorsement_with_arbitrary_branch () = init_genesis () >>=? fun (_genesis, blk) -> - Op.endorsement ~pred_branch:Block_hash.zero blk >>=? fun operation -> + Op.endorsement ~branch:Block_hash.zero blk >>=? fun operation -> Block.bake ~operation blk >>=? fun _blk -> return_unit (****************************************************************) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement.ml index 9107b541ad0c..40b0695d7b54 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement.ml @@ -51,7 +51,7 @@ let init_genesis ?policy () = let test_preendorsement_with_arbitrary_branch () = Context.init1 () >>=? fun (genesis, _contract) -> Block.bake genesis >>=? fun blk -> - Op.preendorsement ~pred_branch:Block_hash.zero blk >>=? fun operation -> + Op.preendorsement ~branch:Block_hash.zero blk >>=? fun operation -> Incremental.begin_construction ~mempool_mode:true blk >>=? fun inc -> Incremental.validate_operation inc operation >>=? fun _inc -> return_unit diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement_functor.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement_functor.ml index 14d283a6ee9f..5002e086384c 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement_functor.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_preendorsement_functor.ml @@ -51,7 +51,6 @@ end = struct let aux_simple_preendorsement_inclusion ?(payload_round = Some Round.zero) ?(locked_round = Some Round.zero) ?(block_round = 1) ?(preend_round = Round.zero) - ?(preend_branch = fun _predpred pred _curr -> pred) ?(preendorsed_block = fun _predpred _pred curr -> curr) ?(mk_ops = fun op -> [op]) ?(get_delegate_and_slot = @@ -61,17 +60,9 @@ end = struct bake genesis >>=? fun b1 -> Op.endorsement b1 >>=? fun endo -> bake b1 ~operations:[endo] >>=? fun b2 -> - let pred_branch = - Some (Context.branch (Context.B (preend_branch genesis b1 b2))) - in let endorsed_block = preendorsed_block genesis b1 b2 in get_delegate_and_slot genesis b1 b2 >>=? fun (delegate, slot) -> - Op.preendorsement - ?delegate - ?slot - ?pred_branch - ~round:preend_round - endorsed_block + Op.preendorsement ?delegate ?slot ~round:preend_round endorsed_block >>=? fun p -> let operations = endo :: (mk_ops @@ p) in bake -- GitLab From 3c762d6173ed12bd13b5c162ac20bb8f67711c23 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 1 Mar 2023 14:12:10 +0100 Subject: [PATCH 03/10] Proto/test_endorsement: update positive tests to test all modes --- .../test/helpers/consensus_helpers.ml | 64 +++++++++++-- .../integration/consensus/test_endorsement.ml | 93 ++++++++++--------- 2 files changed, 101 insertions(+), 56 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml index 5a16c17aa318..8b7cb0e2e245 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml @@ -28,11 +28,17 @@ open Alpha_context type mode = Application | Construction | Mempool +let show_mode = function + | Application -> "Application" + | Construction -> "Construction" + | Mempool -> "Mempool" + type kind = Preendorsement | Endorsement (** Craft an endorsement or preendorsement, and bake a block containing it (in application or construction modes) or inject it - into a mempool. Check that it fails as specified by [error]. + into a mempool. When [error] is [None], check that it succeeds, + otherwise check that it fails as specified by [error]. By default, the (pre)endorsement is for the first slot and is signed by the delegate that owns this slot. Moreover, the operation @@ -43,31 +49,69 @@ type kind = Preendorsement | Endorsement The [endorsed_block] is also used as the predecessor of the baked block, or as the head of the mempool. *) -let test_consensus_operation ?slot ?level ?round ?block_payload_hash - ~endorsed_block ~error ~loc kind mode = +let test_consensus_operation ?slot ?level ?round ?block_payload_hash ?branch + ~endorsed_block ?error ~loc kind mode = let open Lwt_result_syntax in let* operation = match kind with | Preendorsement -> - Op.preendorsement ?slot ?level ?round ?block_payload_hash endorsed_block + Op.preendorsement + ?slot + ?level + ?round + ?block_payload_hash + ?branch + endorsed_block | Endorsement -> - Op.endorsement ?slot ?level ?round ?block_payload_hash endorsed_block + Op.endorsement + ?slot + ?level + ?round + ?block_payload_hash + ?branch + endorsed_block + in + let check_error res = + match error with + | Some error -> Assert.proto_error ~loc res error + | None -> + let*? _ = res in + return_unit in - let assert_error res = Assert.proto_error ~loc res error in match mode with | Application -> Block.bake ~baking_mode:Application ~operation endorsed_block - >>= assert_error + >>= check_error | Construction -> - Block.bake ~baking_mode:Baking ~operation endorsed_block >>= assert_error + Block.bake ~baking_mode:Baking ~operation endorsed_block >>= check_error | Mempool -> let*! res = let* inc = Incremental.begin_construction ~mempool_mode:true endorsed_block in - Incremental.validate_operation inc operation + let* inc = Incremental.add_operation inc operation in + (* Finalization doesn't do much in mempool mode, but some RPCs + still call it, so we check that it doesn't fail unexpectedly. *) + Incremental.finalize_block inc in - assert_error res + check_error res + +let test_consensus_operation_all_modes ?slot ?level ?round ?block_payload_hash + ?branch ~endorsed_block ?error ~loc kind = + List.iter_es + (fun mode -> + test_consensus_operation + ?slot + ?level + ?round + ?block_payload_hash + ?branch + ~endorsed_block + ?error + ~loc:(Format.sprintf "%s (%s mode)" loc (show_mode mode)) + kind + mode) + [Application; Construction; Mempool] let delegate_of_first_slot b = let module V = Plugin.RPC.Validators in diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index 76cf06f5b13f..4ce602c31333 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -41,31 +41,55 @@ let init_genesis ?policy () = Context.init_n ~consensus_threshold:0 5 () >>=? fun (genesis, _contracts) -> Block.bake ?policy genesis >>=? fun b -> return (genesis, b) -(** inject an endorsement and return the block with the endorsement and its - parent. *) -let inject_the_first_endorsement () = - init_genesis () >>=? fun (_genesis, b) -> - Op.endorsement b >>=? fun operation -> - Block.bake ~operation b >>=? fun b' -> return (b', b) - -(****************************************************************) -(* Tests *) -(****************************************************************) +(** {1 Positive tests} *) -(** Apply a single endorsement from the slot 0 endorser. *) +(** Correct endorsement from the slot 0 endorser. *) let test_simple_endorsement () = - inject_the_first_endorsement () >>=? fun (_, _) -> return_unit + let open Lwt_result_syntax in + let* _genesis, endorsed_block = init_genesis () in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block + Endorsement (** Test that the endorsement's branch does not affect its validity. *) -let test_endorsement_with_arbitrary_branch () = - init_genesis () >>=? fun (_genesis, blk) -> - Op.endorsement ~branch:Block_hash.zero blk >>=? fun operation -> - Block.bake ~operation blk >>=? fun _blk -> return_unit +let test_arbitrary_branch () = + let open Lwt_result_syntax in + let* _genesis, endorsed_block = init_genesis () in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block + ~branch:Block_hash.zero + Endorsement + +(** Fitness gap: this is a straightforward update from Emmy to Tenderbake, + that is, check that the level is incremented in a child block. *) +let test_fitness_gap () = + let open Lwt_result_syntax in + let* _genesis, pred_b = init_genesis () in + let* operation = Op.endorsement pred_b in + let* b = Block.bake ~operation pred_b in + let fitness = + match Fitness.from_raw b.header.shell.fitness with + | Ok fitness -> fitness + | _ -> assert false + in + let pred_fitness = + match Fitness.from_raw pred_b.header.shell.fitness with + | Ok fitness -> fitness + | _ -> assert false + in + let level = Fitness.level fitness in + let pred_level = Fitness.level pred_fitness in + let level_diff = + Int32.sub (Raw_level.to_int32 level) (Raw_level.to_int32 pred_level) + in + Assert.equal_int32 ~loc:__LOC__ level_diff 1l + +(** {1 Negative tests} -(****************************************************************) -(* The following test scenarios are supposed to raise errors. *) -(****************************************************************) + The following test scenarios are supposed to raise errors. *) (** Apply an endorsement with a negative slot. *) let test_negative_slot () = @@ -357,27 +381,6 @@ let test_endorsement_threshold ~sufficient_threshold () = if sufficient_threshold then return_unit else Assert.proto_error_with_info ~loc:__LOC__ b "Not enough endorsements" -(** Fitness gap: this is a straightforward update from Emmy to Tenderbake, that - is, check that the level is incremented in a child block. *) -let test_fitness_gap () = - inject_the_first_endorsement () >>=? fun (b, pred_b) -> - let fitness = - match Fitness.from_raw b.header.shell.fitness with - | Ok fitness -> fitness - | _ -> assert false - in - let pred_fitness = - match Fitness.from_raw pred_b.header.shell.fitness with - | Ok fitness -> fitness - | _ -> assert false - in - let level = Fitness.level fitness in - let pred_level = Fitness.level pred_fitness in - let level_diff = - Int32.sub (Raw_level.to_int32 level) (Raw_level.to_int32 pred_level) - in - Assert.equal_int32 ~loc:__LOC__ level_diff 1l - let test_preendorsement_endorsement_same_level () = Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> Block.bake genesis >>=? fun b1 -> @@ -507,18 +510,16 @@ let test_endorsement_grandparent_full_construction () = let tests = [ + (* Positive tests *) Tztest.tztest "Simple endorsement" `Quick test_simple_endorsement; - Tztest.tztest - "Endorsement with arbitrary branch" - `Quick - test_endorsement_with_arbitrary_branch; + Tztest.tztest "Arbitrary branch" `Quick test_arbitrary_branch; + Tztest.tztest "Fitness gap" `Quick test_fitness_gap; + (* Negative tests *) Tztest.tztest "Endorsement with slot -1" `Quick test_negative_slot; Tztest.tztest "Endorsement wrapped with non-normalized slot" `Quick test_non_normalized_slot; - Tztest.tztest "Fitness gap" `Quick test_fitness_gap; - (* Fail scenarios *) Tztest.tztest "Invalid endorsement level" `Quick -- GitLab From 639945a69871520e987b3c87c8c489d9e2da53fc Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Thu, 2 Mar 2023 14:07:29 +0100 Subject: [PATCH 04/10] Proto/test/endorsement: add a positive test with a non-zero round --- .../test/integration/consensus/test_endorsement.ml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index 4ce602c31333..1b2ce863760e 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -63,6 +63,17 @@ let test_arbitrary_branch () = ~branch:Block_hash.zero Endorsement +(** Correct endorsement with a level and a round that are both + different from {!test_simple_endorsement}. *) +let test_non_zero_round () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* endorsed_block = Block.bake ~policy:(By_round 10) b in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block + Endorsement + (** Fitness gap: this is a straightforward update from Emmy to Tenderbake, that is, check that the level is incremented in a child block. *) let test_fitness_gap () = @@ -513,6 +524,7 @@ let tests = (* Positive tests *) Tztest.tztest "Simple endorsement" `Quick test_simple_endorsement; Tztest.tztest "Arbitrary branch" `Quick test_arbitrary_branch; + Tztest.tztest "Non-zero round" `Quick test_non_zero_round; Tztest.tztest "Fitness gap" `Quick test_fitness_gap; (* Negative tests *) Tztest.tztest "Endorsement with slot -1" `Quick test_negative_slot; -- GitLab From 27a2611c9bb880911152f466c33da4dc989f7a6f Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Tue, 28 Feb 2023 16:51:15 +0100 Subject: [PATCH 05/10] Proto/test/endorsement: refactor wrong slot and test all modes --- .../test/helpers/consensus_helpers.ml | 11 +- .../integration/consensus/test_endorsement.ml | 159 +++++++----------- 2 files changed, 69 insertions(+), 101 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml index 8b7cb0e2e245..e944bc0004f4 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml @@ -49,13 +49,14 @@ type kind = Preendorsement | Endorsement The [endorsed_block] is also used as the predecessor of the baked block, or as the head of the mempool. *) -let test_consensus_operation ?slot ?level ?round ?block_payload_hash ?branch - ~endorsed_block ?error ~loc kind mode = +let test_consensus_operation ?delegate ?slot ?level ?round ?block_payload_hash + ?branch ~endorsed_block ?error ~loc kind mode = let open Lwt_result_syntax in let* operation = match kind with | Preendorsement -> Op.preendorsement + ?delegate ?slot ?level ?round @@ -64,6 +65,7 @@ let test_consensus_operation ?slot ?level ?round ?block_payload_hash ?branch endorsed_block | Endorsement -> Op.endorsement + ?delegate ?slot ?level ?round @@ -96,11 +98,12 @@ let test_consensus_operation ?slot ?level ?round ?block_payload_hash ?branch in check_error res -let test_consensus_operation_all_modes ?slot ?level ?round ?block_payload_hash - ?branch ~endorsed_block ?error ~loc kind = +let test_consensus_operation_all_modes ?delegate ?slot ?level ?round + ?block_payload_hash ?branch ~endorsed_block ?error ~loc kind = List.iter_es (fun mode -> test_consensus_operation + ?delegate ?slot ?level ?round diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index 1b2ce863760e..8a5c433648f0 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -102,6 +102,8 @@ let test_fitness_gap () = The following test scenarios are supposed to raise errors. *) +(** {2 Wrong slot} *) + (** Apply an endorsement with a negative slot. *) let test_negative_slot () = Context.init_n 5 () >>=? fun (genesis, _contracts) -> @@ -118,50 +120,63 @@ let test_negative_slot () = (function | Data_encoding.Binary.Write_error _ -> return_unit | e -> Lwt.fail e) -(** Apply an endorsement with a non-normalized slot (that is, not the smallest - possible). *) -let test_non_normalized_slot () = - Context.init_n 5 () >>=? fun (genesis, _contracts) -> - Block.bake genesis >>=? fun b -> - Context.get_endorsers (B b) >>=? fun endorsers_list -> - (* find an endorsers with more than 1 slot *) - List.find_map - (function - | {Plugin.RPC.Validators.delegate; slots; _} -> - if Compare.List_length_with.(slots > 1) then Some (delegate, slots) - else None) - endorsers_list - |> function - | None -> assert false - | Some (delegate, slots) -> - let set_slots = Slot.Set.of_list slots in - (* no duplicated slots *) - Assert.equal_int - ~loc:__LOC__ - (Slot.Set.cardinal set_slots) - (List.length slots) - >>=? fun () -> - (* the first slot should be the smallest slot *) - Assert.equal - ~loc:__LOC__ - (fun x y -> Slot.compare x y = 0) - "the first slot is not the smallest" - Slot.pp - (WithExceptions.Option.get ~loc:__LOC__ @@ List.hd slots) - (WithExceptions.Option.get ~loc:__LOC__ @@ Slot.Set.min_elt set_slots) - >>=? fun () -> - let slot = - match List.hd (List.rev slots) with None -> assert false | Some s -> s - in - Op.endorsement ~delegate ~slot b >>=? fun operation -> - let policy = Block.Excluding [delegate] in - Block.bake ~policy ~operation b >>= fun res -> - Assert.proto_error ~loc:__LOC__ res (function - | Validate_errors.Consensus.Wrong_slot_used_for_consensus_operation - {kind} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) +(** Endorsement with a non-normalized slot (that is, a slot that + belongs to the delegate but is not the delegate's smallest slot). *) +let test_not_smallest_slot () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* endorsers = Context.get_endorsers (B b) in + let delegate, slots = + (* Find an endorser with more than 1 slot. *) + WithExceptions.Option.get + ~loc:__LOC__ + (List.find_map + (fun {RPC.Validators.delegate; slots; _} -> + if Compare.List_length_with.(slots > 1) then Some (delegate, slots) + else None) + endorsers) + in + (* Check that the slots are sorted and have no duplicates. *) + let rec check_sorted = function + | [] | [_] -> true + | x :: (y :: _ as t) -> Slot.compare x y < 0 && check_sorted t + in + assert (check_sorted slots) ; + let slot = + match slots with [] | [_] -> assert false | _ :: slot :: _ -> slot + in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:b + ~delegate + ~slot + ~error:(function + | Validate_errors.Consensus.Wrong_slot_used_for_consensus_operation + {kind; _} + when kind = Validate_errors.Consensus.Endorsement -> + true + | _ -> false) + Endorsement + +(** Endorsement with a slot that does not belong to the delegate. *) +let test_other_delegate_slot () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* endorsers = Context.get_endorsers (B b) in + let delegate, other_delegate_slot = + match endorsers with + | [] | [_] -> assert false (* at least two delegates with rights *) + | {delegate; _} :: {slots; _} :: _ -> + (delegate, WithExceptions.Option.get ~loc:__LOC__ (List.hd slots)) + in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:b + ~delegate + ~slot:other_delegate_slot + ~error:(function + | Alpha_context.Operation.Invalid_signature -> true | _ -> false) + Endorsement (** Invalid_endorsement_level: apply an endorsement with an incorrect level (i.e. the predecessor level). *) @@ -340,26 +355,6 @@ let test_wrong_payload_hash () = Endorsement Application -let test_wrong_slot_used () = - init_genesis () >>=? fun (_genesis, b) -> - Context.get_endorser (B b) >>=? fun (_, slots) -> - (match slots with - | _x :: y :: _ -> return y - | _ -> failwith "Slots size should be at least of 2 ") - >>=? fun slot -> - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:b - ~slot - ~error:(function - | Validate_errors.Consensus.Wrong_slot_used_for_consensus_operation - {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - Endorsement - Application - (** Check that: - a block with not enough endorsement cannot be baked; - a block with enough endorsement is baked. *) @@ -403,27 +398,6 @@ let test_preendorsement_endorsement_same_level () = Incremental.add_operation i op_preendo >>=? fun (_i : Incremental.t) -> return_unit -(** Test for endorsement injection with wrong slot in mempool mode. This - test is expected to fail *) -let test_wrong_endorsement_slot_in_mempool_mode () = - Context.init_n ~consensus_threshold:1 5 () >>=? fun (genesis, _) -> - Block.bake genesis >>=? fun b1 -> - let module V = Plugin.RPC.Validators in - (Context.get_endorsers (B b1) >>=? function - | {V.slots = _ :: non_canonical_slot :: _; _} :: _ -> - (* we didn't use min slot for the injection. It's bad !*) - return (Some non_canonical_slot) - | _ -> assert false) - >>=? fun slot -> - Op.endorsement ?slot b1 >>=? fun endo -> - Incremental.begin_construction ~mempool_mode:true b1 >>=? fun i -> - Incremental.add_operation i endo >>= fun res -> - Assert.proto_error ~loc:__LOC__ res (function - | Validate_errors.Consensus.Wrong_slot_used_for_consensus_operation {kind} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - (** Endorsement for next level *) let test_endorsement_for_next_level () = init_genesis () >>=? fun (genesis, _) -> @@ -527,11 +501,10 @@ let tests = Tztest.tztest "Non-zero round" `Quick test_non_zero_round; Tztest.tztest "Fitness gap" `Quick test_fitness_gap; (* Negative tests *) + (* Wrong slot *) Tztest.tztest "Endorsement with slot -1" `Quick test_negative_slot; - Tztest.tztest - "Endorsement wrapped with non-normalized slot" - `Quick - test_non_normalized_slot; + Tztest.tztest "Non-normalized slot" `Quick test_not_smallest_slot; + Tztest.tztest "Slot of another delegate" `Quick test_other_delegate_slot; Tztest.tztest "Invalid endorsement level" `Quick @@ -567,10 +540,6 @@ let tests = "Wrong payload hash for consensus operation" `Quick test_wrong_payload_hash; - Tztest.tztest - "Wrong slot used for consensus operation" - `Quick - test_wrong_slot_used; Tztest.tztest "sufficient endorsement threshold" `Quick @@ -583,10 +552,6 @@ let tests = "Endorsement/Preendorsement at same level" `Quick test_preendorsement_endorsement_same_level; - Tztest.tztest - "Wrong endorsement slot in mempool mode" - `Quick - test_wrong_endorsement_slot_in_mempool_mode; Tztest.tztest "Endorsement for next level" `Quick -- GitLab From 5ae5338ee7a6b74aa24b6807a61394e02b14217d Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Tue, 28 Feb 2023 17:58:12 +0100 Subject: [PATCH 06/10] Proto/test/endorsement: streamline too old level for all modes --- .../test/helpers/consensus_helpers.ml | 46 +++-- .../integration/consensus/test_endorsement.ml | 177 +++++------------- 2 files changed, 80 insertions(+), 143 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml index e944bc0004f4..cd198517052d 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/consensus_helpers.ml @@ -47,10 +47,12 @@ type kind = Preendorsement | Endorsement predecessor of that block. Optional arguments allow to override these default parameters. - The [endorsed_block] is also used as the predecessor of the baked - block, or as the head of the mempool. *) + The [predecessor] is used as the predecessor of the baked block or + the head of the mempool. When it is not provided, we use the + [endorsed_block] for this. *) let test_consensus_operation ?delegate ?slot ?level ?round ?block_payload_hash - ?branch ~endorsed_block ?error ~loc kind mode = + ?branch ~endorsed_block ?(predecessor = endorsed_block) ?error ~loc kind + mode = let open Lwt_result_syntax in let* operation = match kind with @@ -82,14 +84,13 @@ let test_consensus_operation ?delegate ?slot ?level ?round ?block_payload_hash in match mode with | Application -> - Block.bake ~baking_mode:Application ~operation endorsed_block - >>= check_error + Block.bake ~baking_mode:Application ~operation predecessor >>= check_error | Construction -> - Block.bake ~baking_mode:Baking ~operation endorsed_block >>= check_error + Block.bake ~baking_mode:Baking ~operation predecessor >>= check_error | Mempool -> let*! res = let* inc = - Incremental.begin_construction ~mempool_mode:true endorsed_block + Incremental.begin_construction ~mempool_mode:true predecessor in let* inc = Incremental.add_operation inc operation in (* Finalization doesn't do much in mempool mode, but some RPCs @@ -98,10 +99,11 @@ let test_consensus_operation ?delegate ?slot ?level ?round ?block_payload_hash in check_error res -let test_consensus_operation_all_modes ?delegate ?slot ?level ?round - ?block_payload_hash ?branch ~endorsed_block ?error ~loc kind = +let test_consensus_operation_all_modes_different_outcomes ?delegate ?slot ?level + ?round ?block_payload_hash ?branch ~endorsed_block ?predecessor ~loc + ?application_error ?construction_error ?mempool_error kind = List.iter_es - (fun mode -> + (fun (mode, error) -> test_consensus_operation ?delegate ?slot @@ -110,11 +112,33 @@ let test_consensus_operation_all_modes ?delegate ?slot ?level ?round ?block_payload_hash ?branch ~endorsed_block + ?predecessor ?error ~loc:(Format.sprintf "%s (%s mode)" loc (show_mode mode)) kind mode) - [Application; Construction; Mempool] + [ + (Application, application_error); + (Construction, construction_error); + (Mempool, mempool_error); + ] + +let test_consensus_operation_all_modes ?delegate ?slot ?level ?round + ?block_payload_hash ?branch ~endorsed_block ?predecessor ?error ~loc kind = + test_consensus_operation_all_modes_different_outcomes + ?delegate + ?slot + ?level + ?round + ?block_payload_hash + ?branch + ~endorsed_block + ?predecessor + ~loc + ?application_error:error + ?construction_error:error + ?mempool_error:error + kind let delegate_of_first_slot b = let module V = Plugin.RPC.Validators in diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index 8a5c433648f0..304517b7ba7f 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -178,18 +178,48 @@ let test_other_delegate_slot () = | Alpha_context.Operation.Invalid_signature -> true | _ -> false) Endorsement -(** Invalid_endorsement_level: apply an endorsement with an incorrect - level (i.e. the predecessor level). *) -let test_invalid_endorsement_level () = - init_genesis () >>=? fun (genesis, b) -> - Context.get_level (B genesis) >>?= fun genesis_level -> - Op.endorsement ~level:genesis_level b >>=? fun operation -> - Block.bake ~operation b >>= fun res -> - Assert.proto_error ~loc:__LOC__ res (function - | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) +(** {2 Wrong level} *) + +let error_old_level = function + | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} + when kind = Validate_errors.Consensus.Endorsement -> + true + | _ -> false + +(** Endorsement that is one level too old, aka grandparent endorsement + (the endorsement is expected to point to the level of the + predecessor of the block/mempool containing the endorsement, but + instead it points to the grandparent's level). + + This endorsement should fail in a block (application or + construction), but be accepted in mempool mode. *) +let test_one_level_too_old () = + let open Lwt_result_syntax in + let* _genesis, grandparent = init_genesis () in + let* predecessor = Block.bake grandparent in + Consensus_helpers.test_consensus_operation_all_modes_different_outcomes + ~loc:__LOC__ + ~endorsed_block:grandparent + ~predecessor + ~application_error:error_old_level + ~construction_error:error_old_level + ?mempool_error:None + Endorsement + +(** Endorsement that is two levels too old (pointing to the + great-grandparent instead of the predecessor). It should fail in + all modes. *) +let test_two_levels_too_old () = + let open Lwt_result_syntax in + let* _genesis, greatgrandparent = init_genesis () in + let* grandparent = Block.bake greatgrandparent in + let* predecessor = Block.bake grandparent in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:greatgrandparent + ~predecessor + ~error:error_old_level + Endorsement (** Duplicate endorsement : apply an endorsement that has already been applied. *) let test_duplicate_endorsement () = @@ -222,41 +252,6 @@ let test_consensus_operation_endorsement_for_future_level () = Endorsement Mempool -(** Consensus operation for old level : apply an endorsement one level in the past *) -let test_consensus_operation_endorsement_for_predecessor_level () = - init_genesis () >>=? fun (_genesis, pred) -> - let raw_level = Raw_level.of_int32 (Int32.of_int 0) in - let level = match raw_level with Ok l -> l | Error _ -> assert false in - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:pred - ~level - ~error:(function - | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - Endorsement - Mempool - -(** Consensus operation for old level : apply an endorsement with more than one level in the past *) -let test_consensus_operation_endorsement_for_old_level () = - init_genesis () >>=? fun (genesis, pred) -> - Block.bake genesis >>=? fun _next_block -> - let raw_level = Raw_level.of_int32 (Int32.of_int 0) in - let level = match raw_level with Ok l -> l | Error _ -> assert false in - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:pred - ~level - ~error:(function - | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - Endorsement - Mempool - (** Consensus operation for future round : apply an endorsement with a round in the future *) let test_consensus_operation_endorsement_for_future_round () = init_genesis () >>=? fun (_genesis, pred) -> @@ -321,24 +316,6 @@ let test_wrong_round () = Endorsement Application -(** Wrong level : apply an endorsement with an incorrect level *) -let test_wrong_level () = - init_genesis () >>=? fun (_genesis, b) -> - (* let context = Context.B genesis in*) - let raw_level = Raw_level.of_int32 (Int32.of_int 0) in - let level = match raw_level with Ok l -> l | Error _ -> assert false in - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:b - ~level - ~error:(function - | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - Endorsement - Application - (** Wrong payload hash : apply an endorsement with an incorrect payload hash *) let test_wrong_payload_hash () = init_genesis () >>=? fun (_genesis, b) -> @@ -414,20 +391,6 @@ let test_endorsement_for_next_round () = ~kind:`Endorsement ~next:`Round -(** Endorsement of grandparent *) -let test_endorsement_grandparent () = - Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> - Block.bake genesis >>=? fun b_gp -> - Block.bake b_gp >>=? fun b -> - Incremental.begin_construction ~mempool_mode:true b >>=? fun i -> - (* Endorsement on grandparent *) - Op.endorsement b_gp >>=? fun op1 -> - (* Endorsement on parent *) - Op.endorsement b >>=? fun op2 -> - (* Both should be accepted by the mempool *) - Incremental.add_operation i op1 >>=? fun i -> - Incremental.add_operation i op2 >>=? fun (_i : Incremental.t) -> return_unit - (** Double inclusion of grandparent endorsement *) let test_double_endorsement_grandparent () = Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> @@ -465,34 +428,6 @@ let test_endorsement_grandparent_same_slot () = Incremental.add_operation i op1 >>=? fun i -> Incremental.add_operation i op2 >>=? fun (_i : Incremental.t) -> return_unit -(** Endorsement of grandparent in application mode should be rejected *) -let test_endorsement_grandparent_application () = - Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> - Block.bake genesis >>=? fun b_gp -> - Block.bake b_gp >>=? fun b -> - Op.endorsement b_gp >>=? fun operation -> - Block.bake ~operation b >>= fun res -> - Assert.proto_error ~loc:__LOC__ res (function - | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - -(** Endorsement of grandparent in full construction mode should be rejected *) -let test_endorsement_grandparent_full_construction () = - Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> - Block.bake genesis >>=? fun b_gp -> - Block.bake b_gp >>=? fun b -> - Incremental.begin_construction b >>=? fun i -> - (* Endorsement on grandparent *) - Op.endorsement b_gp >>=? fun op1 -> - Incremental.add_operation i op1 >>= fun res -> - Assert.proto_error ~loc:__LOC__ res (function - | Validate_errors.Consensus.Consensus_operation_for_old_level {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - let tests = [ (* Positive tests *) @@ -505,23 +440,14 @@ let tests = Tztest.tztest "Endorsement with slot -1" `Quick test_negative_slot; Tztest.tztest "Non-normalized slot" `Quick test_not_smallest_slot; Tztest.tztest "Slot of another delegate" `Quick test_other_delegate_slot; - Tztest.tztest - "Invalid endorsement level" - `Quick - test_invalid_endorsement_level; + (* Wrong level *) + Tztest.tztest "One level too old" `Quick test_one_level_too_old; + Tztest.tztest "Two levels too old" `Quick test_two_levels_too_old; Tztest.tztest "Duplicate endorsement" `Quick test_duplicate_endorsement; Tztest.tztest "Endorsement for future level" `Quick test_consensus_operation_endorsement_for_future_level; - Tztest.tztest - "Endorsement for predecessor level" - `Quick - test_consensus_operation_endorsement_for_old_level; - Tztest.tztest - "Endorsement for old level" - `Quick - test_consensus_operation_endorsement_for_old_level; Tztest.tztest "Endorsement for future round" `Quick @@ -534,7 +460,6 @@ let tests = "Endorsement on competing proposal" `Quick test_consensus_operation_endorsement_on_competing_proposal; - Tztest.tztest "Wrong level for consensus operation" `Quick test_wrong_level; Tztest.tztest "Wrong round for consensus operation" `Quick test_wrong_round; Tztest.tztest "Wrong payload hash for consensus operation" @@ -560,10 +485,6 @@ let tests = "Endorsement for next round" `Quick test_endorsement_for_next_round; - Tztest.tztest - "Endorsement for grandparent" - `Quick - test_endorsement_grandparent; Tztest.tztest "Double endorsement of grandparent" `Quick @@ -572,12 +493,4 @@ let tests = "Endorsement for grandparent on same slot as parent" `Quick test_endorsement_grandparent_same_slot; - Tztest.tztest - "Endorsement for grandparent in application mode" - `Quick - test_endorsement_grandparent_application; - Tztest.tztest - "Endorsement for grandparent in full construction mode" - `Quick - test_endorsement_grandparent_full_construction; ] -- GitLab From c3d92a78898cb10bd9579237543047d41ac7321a Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 1 Mar 2023 14:52:50 +0100 Subject: [PATCH 07/10] Proto/test/endorsement: streamline future level for all modes --- .../integration/consensus/test_endorsement.ml | 69 ++++++++++--------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index 304517b7ba7f..0eafd9b8b074 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -221,6 +221,40 @@ let test_two_levels_too_old () = ~error:error_old_level Endorsement +let error_future_level = function + | Validate_errors.Consensus.Consensus_operation_for_future_level {kind; _} + when kind = Validate_errors.Consensus.Endorsement -> + true + | _ -> false + +(** Endorsement that is one level in the future (pointing to the same + level as the block/mempool containing the endorsement instead of + its predecessor/head). It should fail in all modes. *) +let test_one_level_in_the_future () = + let open Lwt_result_syntax in + let* _genesis, predecessor = init_genesis () in + let* next_level_block = Block.bake predecessor in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:next_level_block + ~predecessor + ~error:error_future_level + Endorsement + +(** Endorsement that is two levels in the future. It should fail in + all modes. *) +let test_two_levels_future () = + let open Lwt_result_syntax in + let* _genesis, predecessor = init_genesis () in + let* next_level_block = Block.bake predecessor in + let* after_next_level_block = Block.bake next_level_block in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:after_next_level_block + ~predecessor + ~error:error_future_level + Endorsement + (** Duplicate endorsement : apply an endorsement that has already been applied. *) let test_duplicate_endorsement () = init_genesis () >>=? fun (_genesis, b) -> @@ -235,23 +269,6 @@ let test_duplicate_endorsement () = true | _ -> false) -(** Consensus operation for future level : apply an endorsement with a level in the future *) -let test_consensus_operation_endorsement_for_future_level () = - init_genesis () >>=? fun (_genesis, pred) -> - let raw_level = Raw_level.of_int32 (Int32.of_int 10) in - let level = match raw_level with Ok l -> l | Error _ -> assert false in - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:pred - ~level - ~error:(function - | Validate_errors.Consensus.Consensus_operation_for_future_level {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - Endorsement - Mempool - (** Consensus operation for future round : apply an endorsement with a round in the future *) let test_consensus_operation_endorsement_for_future_round () = init_genesis () >>=? fun (_genesis, pred) -> @@ -375,14 +392,6 @@ let test_preendorsement_endorsement_same_level () = Incremental.add_operation i op_preendo >>=? fun (_i : Incremental.t) -> return_unit -(** Endorsement for next level *) -let test_endorsement_for_next_level () = - init_genesis () >>=? fun (genesis, _) -> - Consensus_helpers.test_consensus_op_for_next - ~genesis - ~kind:`Endorsement - ~next:`Level - (** Endorsement for next round *) let test_endorsement_for_next_round () = init_genesis () >>=? fun (genesis, _) -> @@ -443,11 +452,9 @@ let tests = (* Wrong level *) Tztest.tztest "One level too old" `Quick test_one_level_too_old; Tztest.tztest "Two levels too old" `Quick test_two_levels_too_old; + Tztest.tztest "One level in the future" `Quick test_one_level_in_the_future; + Tztest.tztest "Two levels in the future" `Quick test_two_levels_future; Tztest.tztest "Duplicate endorsement" `Quick test_duplicate_endorsement; - Tztest.tztest - "Endorsement for future level" - `Quick - test_consensus_operation_endorsement_for_future_level; Tztest.tztest "Endorsement for future round" `Quick @@ -477,10 +484,6 @@ let tests = "Endorsement/Preendorsement at same level" `Quick test_preendorsement_endorsement_same_level; - Tztest.tztest - "Endorsement for next level" - `Quick - test_endorsement_for_next_level; Tztest.tztest "Endorsement for next round" `Quick -- GitLab From d203f0a29697ed13476b004a1a9ed0405a655079 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 1 Mar 2023 15:30:00 +0100 Subject: [PATCH 08/10] Proto/test/endorsement: streamline wrong round for all modes --- .../integration/consensus/test_endorsement.ml | 141 +++++++++--------- 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index 0eafd9b8b074..c99faefeb7d0 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -255,6 +255,73 @@ let test_two_levels_future () = ~error:error_future_level Endorsement +(** {2 Wrong round} *) + +let error_old_round = function + | Validate_errors.Consensus.Consensus_operation_for_old_round {kind; _} + when kind = Validate_errors.Consensus.Endorsement -> + true + | _ -> false + +(** Endorsement that is one round too old. It should fail in all modes. *) +let test_one_round_too_old () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* round0_block = Block.bake b in + let* predecessor = Block.bake ~policy:(By_round 1) b in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:round0_block + ~predecessor + ~error:error_old_round + Endorsement + +(** Endorsement that is many rounds too old. It should fail in all modes. *) +let test_many_rounds_too_old () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* round5_block = Block.bake ~policy:(By_round 5) b in + let* predecessor = Block.bake ~policy:(By_round 15) b in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:round5_block + ~predecessor + ~error:error_old_round + Endorsement + +let error_future_round = function + | Validate_errors.Consensus.Consensus_operation_for_future_round {kind; _} + when kind = Validate_errors.Consensus.Endorsement -> + true + | _ -> false + +(** Endorsement that is one round in the future. It should fail in all modes. *) +let test_one_round_in_the_future () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* predecessor = Block.bake b in + let* round1_block = Block.bake ~policy:(By_round 1) b in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:round1_block + ~predecessor + ~error:error_future_round + Endorsement + +(** Endorsement that is many rounds in the future. It should fail in + all modes. *) +let test_many_rounds_future () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* predecessor = Block.bake ~policy:(By_round 5) b in + let* round15_block = Block.bake ~policy:(By_round 15) b in + Consensus_helpers.test_consensus_operation_all_modes + ~loc:__LOC__ + ~endorsed_block:round15_block + ~predecessor + ~error:error_future_round + Endorsement + (** Duplicate endorsement : apply an endorsement that has already been applied. *) let test_duplicate_endorsement () = init_genesis () >>=? fun (_genesis, b) -> @@ -269,38 +336,6 @@ let test_duplicate_endorsement () = true | _ -> false) -(** Consensus operation for future round : apply an endorsement with a round in the future *) -let test_consensus_operation_endorsement_for_future_round () = - init_genesis () >>=? fun (_genesis, pred) -> - Environment.wrap_tzresult (Round.of_int 21) >>?= fun round -> - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:pred - ~round - ~error:(function - | Validate_errors.Consensus.Consensus_operation_for_future_round {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - Endorsement - Mempool - -(** Consensus operation for old round : apply an endorsement with a round in the past *) -let test_consensus_operation_endorsement_for_old_round () = - init_genesis ~policy:(By_round 10) () >>=? fun (_genesis, pred) -> - Environment.wrap_tzresult (Round.of_int 0) >>?= fun round -> - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:pred - ~round - ~error:(function - | Validate_errors.Consensus.Consensus_operation_for_old_round {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - Endorsement - Mempool - (** Consensus operation on competing proposal : apply an endorsement on a competing proposal *) let test_consensus_operation_endorsement_on_competing_proposal () = init_genesis () >>=? fun (_genesis, pred) -> @@ -317,22 +352,6 @@ let test_consensus_operation_endorsement_on_competing_proposal () = Endorsement Mempool -(** Wrong round : apply an endorsement with an incorrect round *) -let test_wrong_round () = - init_genesis () >>=? fun (_genesis, b) -> - Environment.wrap_tzresult (Round.of_int 2) >>?= fun round -> - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:b - ~round - ~error:(function - | Validate_errors.Consensus.Consensus_operation_for_future_round {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) - Endorsement - Application - (** Wrong payload hash : apply an endorsement with an incorrect payload hash *) let test_wrong_payload_hash () = init_genesis () >>=? fun (_genesis, b) -> @@ -392,14 +411,6 @@ let test_preendorsement_endorsement_same_level () = Incremental.add_operation i op_preendo >>=? fun (_i : Incremental.t) -> return_unit -(** Endorsement for next round *) -let test_endorsement_for_next_round () = - init_genesis () >>=? fun (genesis, _) -> - Consensus_helpers.test_consensus_op_for_next - ~genesis - ~kind:`Endorsement - ~next:`Round - (** Double inclusion of grandparent endorsement *) let test_double_endorsement_grandparent () = Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> @@ -454,20 +465,16 @@ let tests = Tztest.tztest "Two levels too old" `Quick test_two_levels_too_old; Tztest.tztest "One level in the future" `Quick test_one_level_in_the_future; Tztest.tztest "Two levels in the future" `Quick test_two_levels_future; + (* Wrong round *) + Tztest.tztest "One round too old" `Quick test_one_round_too_old; + Tztest.tztest "Many rounds too old" `Quick test_many_rounds_too_old; + Tztest.tztest "One round in the future" `Quick test_one_round_in_the_future; + Tztest.tztest "Many rounds in the future" `Quick test_many_rounds_future; Tztest.tztest "Duplicate endorsement" `Quick test_duplicate_endorsement; - Tztest.tztest - "Endorsement for future round" - `Quick - test_consensus_operation_endorsement_for_future_round; - Tztest.tztest - "Endorsement for old round" - `Quick - test_consensus_operation_endorsement_for_old_round; Tztest.tztest "Endorsement on competing proposal" `Quick test_consensus_operation_endorsement_on_competing_proposal; - Tztest.tztest "Wrong round for consensus operation" `Quick test_wrong_round; Tztest.tztest "Wrong payload hash for consensus operation" `Quick @@ -484,10 +491,6 @@ let tests = "Endorsement/Preendorsement at same level" `Quick test_preendorsement_endorsement_same_level; - Tztest.tztest - "Endorsement for next round" - `Quick - test_endorsement_for_next_round; Tztest.tztest "Double endorsement of grandparent" `Quick -- GitLab From bce952346f66631e0f02d7fa00e74059f1e0c878 Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 1 Mar 2023 15:35:47 +0100 Subject: [PATCH 09/10] Proto/test/endorsement: factorize wrong payload hash for all modes --- .../integration/consensus/test_endorsement.ml | 56 ++++++------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index c99faefeb7d0..05df583a3cff 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -322,26 +322,15 @@ let test_many_rounds_future () = ~error:error_future_round Endorsement -(** Duplicate endorsement : apply an endorsement that has already been applied. *) -let test_duplicate_endorsement () = - init_genesis () >>=? fun (_genesis, b) -> - Incremental.begin_construction b >>=? fun inc -> - Op.endorsement b >>=? fun operation -> - Incremental.add_operation inc operation >>=? fun inc -> - Op.endorsement b >>=? fun operation -> - Incremental.add_operation inc operation >>= fun res -> - Assert.proto_error ~loc:__LOC__ res (function - | Validate_errors.Consensus.Conflicting_consensus_operation {kind; _} - when kind = Validate_errors.Consensus.Endorsement -> - true - | _ -> false) +(** {2 Wrong payload hash} *) -(** Consensus operation on competing proposal : apply an endorsement on a competing proposal *) -let test_consensus_operation_endorsement_on_competing_proposal () = - init_genesis () >>=? fun (_genesis, pred) -> - Consensus_helpers.test_consensus_operation +(** Endorsement with an incorrect payload hash. *) +let test_wrong_payload_hash () = + let open Lwt_result_syntax in + let* _genesis, endorsed_block = init_genesis () in + Consensus_helpers.test_consensus_operation_all_modes ~loc:__LOC__ - ~endorsed_block:pred + ~endorsed_block ~block_payload_hash:Block_payload_hash.zero ~error:(function | Validate_errors.Consensus.Wrong_payload_hash_for_consensus_operation @@ -350,23 +339,20 @@ let test_consensus_operation_endorsement_on_competing_proposal () = true | _ -> false) Endorsement - Mempool -(** Wrong payload hash : apply an endorsement with an incorrect payload hash *) -let test_wrong_payload_hash () = +(** Duplicate endorsement : apply an endorsement that has already been applied. *) +let test_duplicate_endorsement () = init_genesis () >>=? fun (_genesis, b) -> - Consensus_helpers.test_consensus_operation - ~loc:__LOC__ - ~endorsed_block:b - ~block_payload_hash:Block_payload_hash.zero - ~error:(function - | Validate_errors.Consensus.Wrong_payload_hash_for_consensus_operation - {kind; _} + Incremental.begin_construction b >>=? fun inc -> + Op.endorsement b >>=? fun operation -> + Incremental.add_operation inc operation >>=? fun inc -> + Op.endorsement b >>=? fun operation -> + Incremental.add_operation inc operation >>= fun res -> + Assert.proto_error ~loc:__LOC__ res (function + | Validate_errors.Consensus.Conflicting_consensus_operation {kind; _} when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) - Endorsement - Application (** Check that: - a block with not enough endorsement cannot be baked; @@ -470,15 +456,9 @@ let tests = Tztest.tztest "Many rounds too old" `Quick test_many_rounds_too_old; Tztest.tztest "One round in the future" `Quick test_one_round_in_the_future; Tztest.tztest "Many rounds in the future" `Quick test_many_rounds_future; + (* Wrong payload hash *) + Tztest.tztest "Wrong payload hash" `Quick test_wrong_payload_hash; Tztest.tztest "Duplicate endorsement" `Quick test_duplicate_endorsement; - Tztest.tztest - "Endorsement on competing proposal" - `Quick - test_consensus_operation_endorsement_on_competing_proposal; - Tztest.tztest - "Wrong payload hash for consensus operation" - `Quick - test_wrong_payload_hash; Tztest.tztest "sufficient endorsement threshold" `Quick -- GitLab From 8856bb867b7f85295cff28762bf9cc2e590f8f6b Mon Sep 17 00:00:00 2001 From: Diane Gallois-Wong Date: Wed, 1 Mar 2023 18:45:57 +0100 Subject: [PATCH 10/10] Proto/test/endorsement: conflict tests --- .../integration/consensus/test_endorsement.ml | 198 ++++++++++++------ 1 file changed, 130 insertions(+), 68 deletions(-) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml index 05df583a3cff..a1d12e676c44 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_endorsement.ml @@ -340,20 +340,127 @@ let test_wrong_payload_hash () = | _ -> false) Endorsement -(** Duplicate endorsement : apply an endorsement that has already been applied. *) -let test_duplicate_endorsement () = - init_genesis () >>=? fun (_genesis, b) -> - Incremental.begin_construction b >>=? fun inc -> - Op.endorsement b >>=? fun operation -> - Incremental.add_operation inc operation >>=? fun inc -> - Op.endorsement b >>=? fun operation -> - Incremental.add_operation inc operation >>= fun res -> - Assert.proto_error ~loc:__LOC__ res (function +(** {1 Conflict tests} + + Some positive and some negative tests. *) + +let assert_conflict_error ~loc res = + Assert.proto_error ~loc res (function | Validate_errors.Consensus.Conflicting_consensus_operation {kind; _} when kind = Validate_errors.Consensus.Endorsement -> true | _ -> false) +(** Test that endorsements conflict with: + - an identical endorsement, and + - an endorsement on the same block with a different branch. *) +let test_conflict () = + let open Lwt_result_syntax in + let* _genesis, b = init_genesis () in + let* op = Op.endorsement b in + let* op_different_branch = Op.endorsement ~branch:Block_hash.zero b in + (* Test in application and construction (aka baking) modes *) + let assert_conflict loc baking_mode tested_op = + Block.bake ~baking_mode ~operations:[op; tested_op] b + >>= assert_conflict_error ~loc + in + let* () = assert_conflict __LOC__ Application op in + let* () = assert_conflict __LOC__ Application op_different_branch in + let* () = assert_conflict __LOC__ Baking op in + let* () = assert_conflict __LOC__ Baking op_different_branch in + (* Test in mempool mode. *) + let* inc = Incremental.begin_construction ~mempool_mode:true b in + let* inc = Incremental.validate_operation inc op in + let assert_mempool_conflict loc tested_op = + Incremental.validate_operation inc tested_op >>= assert_conflict_error ~loc + in + let* () = assert_mempool_conflict __LOC__ op in + let* () = assert_mempool_conflict __LOC__ op_different_branch in + return_unit + +(** In mempool mode, test that grandparent endorsements conflict with: + - an identical endorsement, and + - an endorsement on the same block with a different branch. + + This test would make no sense in application or construction modes, + since grandparent endorsements fail anyway (as can be observed in + {!test_one_level_too_old}). *) +let test_grandparent_conflict () = + let open Lwt_result_syntax in + let* _genesis, grandparent = init_genesis () in + let* predecessor = Block.bake grandparent in + let* op = Op.endorsement grandparent in + let* op_different_branch = + Op.endorsement ~branch:Block_hash.zero grandparent + in + let* inc = Incremental.begin_construction ~mempool_mode:true predecessor in + let* inc = Incremental.validate_operation inc op in + let assert_conflict loc tested_op = + Incremental.validate_operation inc tested_op >>= assert_conflict_error ~loc + in + let* () = assert_conflict __LOC__ op in + let* () = assert_conflict __LOC__ op_different_branch in + return_unit + +(** In mempool mode, test that there is no conflict between an + endorsement and a preendorsement for the same slot (here the first + slot), same level, and same round. *) +let test_no_conflict_with_preendorsement_mempool () = + let open Lwt_result_syntax in + let* _genesis, endorsed_block = init_genesis () in + let* op_endo = Op.endorsement endorsed_block in + let* op_preendo = Op.preendorsement endorsed_block in + let* inc = Incremental.begin_construction ~mempool_mode:true endorsed_block in + let* inc = Incremental.add_operation inc op_endo in + let* inc = Incremental.add_operation inc op_preendo in + let* _inc = Incremental.finalize_block inc in + return_unit + +(** In application and construction (aka baking) modes, test that + there is no conflict between an endorsement and a preendorsement + for the same slot (here the first slot). Note that the operations + don't have the same level because the required levels for them to + be valid are different. *) +let test_no_conflict_with_preendorsement_block () = + let open Lwt_result_syntax in + let* _genesis, predecessor = init_genesis () in + let* round0_block = Block.bake predecessor in + let* op_endo = Op.endorsement predecessor in + let* op_preendo = Op.preendorsement round0_block in + let bake_both_ops baking_mode = + Block.bake + ~baking_mode + ~payload_round:(Some Round.zero) + ~locked_round:(Some Round.zero) + ~policy:(By_round 1) + ~operations:[op_endo; op_preendo] + predecessor + in + let* (_ : Block.t) = bake_both_ops Application in + let* (_ : Block.t) = bake_both_ops Baking in + return_unit + +(** In mempool mode, test that there is no conflict between a normal + endorsement (for the predecessor) and a grandparent endorsement, + both for the same slot (here the first slot). There is no similar + test in application and construction modes because grandparent + endorsements are not valid then. *) +let test_no_conflict_with_grandparent () = + let open Lwt_result_syntax in + let* _genesis, grandparent = init_genesis () in + let* predecessor = Block.bake grandparent in + let* op_normal = Op.endorsement predecessor in + let* op_grandparent = Op.endorsement grandparent in + let* inc = Incremental.begin_construction ~mempool_mode:true predecessor in + let* inc = Incremental.add_operation inc op_normal in + let* inc = Incremental.add_operation inc op_grandparent in + let* _inc = Incremental.finalize_block inc in + return_unit + +(** {1 Consensus threshold tests} + + Both positive and negative tests. *) + (** Check that: - a block with not enough endorsement cannot be baked; - a block with enough endorsement is baked. *) @@ -386,54 +493,6 @@ let test_endorsement_threshold ~sufficient_threshold () = if sufficient_threshold then return_unit else Assert.proto_error_with_info ~loc:__LOC__ b "Not enough endorsements" -let test_preendorsement_endorsement_same_level () = - Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> - Block.bake genesis >>=? fun b1 -> - Incremental.begin_construction ~mempool_mode:true ~policy:(By_round 2) b1 - >>=? fun i -> - Op.endorsement b1 >>=? fun op_endo -> - Incremental.add_operation i op_endo >>=? fun (_i : Incremental.t) -> - Op.preendorsement b1 >>=? fun op_preendo -> - Incremental.add_operation i op_preendo >>=? fun (_i : Incremental.t) -> - return_unit - -(** Double inclusion of grandparent endorsement *) -let test_double_endorsement_grandparent () = - Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> - Block.bake genesis >>=? fun b_gp -> - Block.bake b_gp >>=? fun b -> - Incremental.begin_construction ~mempool_mode:true b >>=? fun i -> - (* Endorsement on grandparent *) - Op.endorsement b_gp >>=? fun op1 -> - (* Endorsement on parent *) - Op.endorsement b >>=? fun op2 -> - (* The first grand parent endorsement should be accepted by the - mempool but the second rejected. *) - Incremental.add_operation i op1 >>=? fun i -> - Incremental.add_operation i op1 >>= fun res -> - Assert.proto_error_with_info - ~loc:__LOC__ - res - "Double inclusion of consensus operation" - >>=? fun () -> - Incremental.add_operation i op2 >>=? fun (_i : Incremental.t) -> return_unit - -(** Endorsement of grandparent on same slot as parent *) -let test_endorsement_grandparent_same_slot () = - Context.init1 ~consensus_threshold:0 () >>=? fun (genesis, _contract) -> - Block.bake genesis >>=? fun b_gp -> - Block.bake b_gp >>=? fun b -> - Incremental.begin_construction ~mempool_mode:true b >>=? fun i -> - (* Endorsement on parent *) - Consensus_helpers.delegate_of_first_slot (B b) >>=? fun (delegate, slot) -> - Op.endorsement ~delegate b >>=? fun op2 -> - (* Endorsement on grandparent *) - Consensus_helpers.delegate_of_slot slot (B b_gp) >>=? fun delegate -> - Op.endorsement ~delegate b_gp >>=? fun op1 -> - (* Both should be accepted by the mempool *) - Incremental.add_operation i op1 >>=? fun i -> - Incremental.add_operation i op2 >>=? fun (_i : Incremental.t) -> return_unit - let tests = [ (* Positive tests *) @@ -458,25 +517,28 @@ let tests = Tztest.tztest "Many rounds in the future" `Quick test_many_rounds_future; (* Wrong payload hash *) Tztest.tztest "Wrong payload hash" `Quick test_wrong_payload_hash; - Tztest.tztest "Duplicate endorsement" `Quick test_duplicate_endorsement; + (* Conflict tests (some negative, some positive) *) + Tztest.tztest "Conflict" `Quick test_conflict; + Tztest.tztest "Grandparent conflict" `Quick test_grandparent_conflict; Tztest.tztest - "sufficient endorsement threshold" + "No conflict with preendorsement (mempool)" `Quick - (test_endorsement_threshold ~sufficient_threshold:true); + test_no_conflict_with_preendorsement_mempool; Tztest.tztest - "insufficient endorsement threshold" + "No conflict with preendorsement (block)" `Quick - (test_endorsement_threshold ~sufficient_threshold:false); + test_no_conflict_with_preendorsement_block; Tztest.tztest - "Endorsement/Preendorsement at same level" + "No conflict with grandparent endorsement" `Quick - test_preendorsement_endorsement_same_level; + test_no_conflict_with_grandparent; + (* Consensus threshold tests (one positive and one negative) *) Tztest.tztest - "Double endorsement of grandparent" + "sufficient endorsement threshold" `Quick - test_double_endorsement_grandparent; + (test_endorsement_threshold ~sufficient_threshold:true); Tztest.tztest - "Endorsement for grandparent on same slot as parent" + "insufficient endorsement threshold" `Quick - test_endorsement_grandparent_same_slot; + (test_endorsement_threshold ~sufficient_threshold:false); ] -- GitLab