diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/block.ml b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/block.ml index 80e6286b7b351b17425e12fae9f8954719f81f4c..c25500bafeea78ac5a4253dde6564990e57e84b5 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/block.ml +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/block.ml @@ -41,6 +41,8 @@ type t = { type block = t +type full_metadata = block_header_metadata * operation_receipt list + let get_alpha_ctxt b = let open Lwt_result_wrap_syntax in let*@ ctxt, _migration_balance_updates, _migration_operation_results = diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/block.mli b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/block.mli index a703ec3ec13d48ec72f1d6ad882ba5b5feec7712..4315ccb8b8f66e441d511362f4785967de88a082 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/block.mli +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/block.mli @@ -39,6 +39,8 @@ type t = { type block = t +type full_metadata = block_header_metadata * operation_receipt list + (** Not the same as [Context.get_alpha_ctxt] as it does not construct a new block *) val get_alpha_ctxt : t -> context tzresult Lwt.t diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/incremental.ml b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/incremental.ml index 44d8ed58a0b290e44c8745467e695e7247291727..ad3732df75410dc9549155001e2b124249ee6965 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/incremental.ml +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/incremental.ml @@ -47,6 +47,8 @@ let rev_operations {rev_operations; _} = rev_operations let rev_tickets {rev_tickets; _} = rev_tickets +let delegate {delegate; _} = delegate + let validation_state {state = vs, _; _} = vs let level st = st.header.shell.level diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/incremental.mli b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/incremental.mli index 301765a0721549fcb10ec704a1f623e705db2e77..9c813180a733d7eeca9d6b5d20199d2de18ea666 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/incremental.mli +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/incremental.mli @@ -38,6 +38,8 @@ val rev_operations : incremental -> Operation.packed list val rev_tickets : incremental -> operation_receipt list +val delegate : incremental -> Account.t + val validation_state : incremental -> validation_state val level : incremental -> int32 diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_bake.ml b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_bake.ml index fd25cc076cfaa258eb1da7da3042ae1a4b4fd7d0..98ecdaad3f9cfb3932e6e7aa70e5887ff3627442 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_bake.ml +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_bake.ml @@ -284,11 +284,20 @@ let check_ai_launch_cycle_is_zero ~loc block = Test.fail ~__LOC__:loc "AI launch cycle should always be zero" ; return_unit -(** Bake a block, with the given baker and the given operations. *) -let bake ?baker : t -> t tzresult Lwt.t = +(** Apply all operations pending in the [state]. + It is imperative that the list of pending operations in the state + is empty before finalizing the block, either manually, or by calling this function. *) +let apply_all_pending_operations_ : t_incr -> t_incr tzresult Lwt.t = + fun (i, state) -> + let open Lwt_result_wrap_syntax in + let state, operations = State.pop_pending_operations state in + let* i = List.fold_left_es Incremental.add_operation i operations in + return (i, state) + +(** finalize the payload of the next block. Can start including preattestations. *) +let finalize_payload_ ?payload_round ?baker : t -> t_incr tzresult Lwt.t = fun (block, state) -> let open Lwt_result_wrap_syntax in - let previous_block = block in let policy = match baker with | None -> state.baking_policy @@ -308,7 +317,6 @@ let bake ?baker : t -> t tzresult Lwt.t = let baker_name, {contract = baker_contract; _} = State.find_account_from_pkh baker state in - let current_cycle = Block.current_cycle block in let* level = Plugin.RPC.current_level Block.rpc_ctxt block in let* next_level = let* ctxt = Context.get_alpha_ctxt (B block) in @@ -327,16 +335,17 @@ let bake ?baker : t -> t tzresult Lwt.t = else Per_block_vote_pass in let* () = check_issuance_rpc block in - let state, operations = State.pop_pending_operations state in - let* block, state = - let* block', _metadata = - Block.bake_with_metadata ?policy ~adaptive_issuance_vote ~operations block - in + let* block' = Block.bake ?policy ~adaptive_issuance_vote block in + let* i = + Incremental.begin_construction + ?payload_round + ~payload:state.pending_operations + ?policy + ~adaptive_issuance_vote + block + in + let* i, state = if state.burn_rewards then - (* Incremental mode *) - let* i = - Incremental.begin_construction ?policy ~adaptive_issuance_vote block - in let* block_rewards = Context.get_issuance_per_minute (B block') in let ctxt = Incremental.alpha_ctxt i in let*@ context, _ = @@ -347,13 +356,26 @@ let bake ?baker : t -> t tzresult Lwt.t = block_rewards in let i = Incremental.set_alpha_ctxt i context in - let* i = List.fold_left_es Incremental.add_operation i operations in - let* block = Incremental.finalize_block i in let state = State.apply_burn block_rewards baker_name state in - return (block, state) - else return (block', state) + return (i, state) + else return (i, state) + in + apply_all_pending_operations_ (i, state) + +let finalize_payload ?payload_round ?baker () : (t, t_incr) scenarios = + exec (finalize_payload_ ?payload_round ?baker) + +let finalize_block_ : t_incr -> t tzresult Lwt.t = + fun (i, state) -> + let open Lwt_result_wrap_syntax in + assert (List.is_empty state.pending_operations) ; + let* block, block_metadata = Incremental.finalize_block_with_metadata i in + let ((_, op_metadata) as metadata) = + (block_metadata, List.rev (Incremental.rev_tickets i)) in - let baker_acc = State.find_account baker_name state in + let previous_block = Incremental.predecessor i in + let baker = Incremental.delegate i in + let baker_name, baker_acc = State.find_account_from_pkh baker.pkh state in (* update baker and attesters activity *) let update_activity delegate_account = Account_helpers.update_activity @@ -362,26 +384,25 @@ let bake ?baker : t -> t tzresult Lwt.t = (Block.current_cycle block) in let* attesters = - let open Tezos_raw_protocol_023_PtSeouLo.Alpha_context in - let* ctxt = Context.get_alpha_ctxt (B previous_block) in List.filter_map_es - (fun op -> - let ({protocol_data = Operation_data protocol_data; _} - : packed_operation) = - op - in - match protocol_data.contents with - | Single (Attestation {consensus_content; _}) -> - let*@ _, owner = - Stake_distribution.slot_owner - ctxt - (Level.from_raw ctxt consensus_content.level) - consensus_content.slot - in - return_some owner.delegate - | _ -> return_none) - operations + (function + | Protocol.Apply_results.No_operation_metadata -> return_none + | Operation_metadata {contents} -> ( + match contents with + | Single_result (Attestation_result {delegate; _}) + | Single_result (Preattestation_result {delegate; _}) -> + return_some [delegate] + | Single_result (Attestations_aggregate_result {committee; _}) + | Single_result (Preattestations_aggregate_result {committee; _}) -> + return_some + (List.map + (fun ((ck : Protocol.Alpha_context.Consensus_key.t), _) -> + ck.delegate) + committee) + | _ -> return_none)) + op_metadata in + let attesters = List.flatten attesters in let state = State.update_map ~f:(fun acc_map -> @@ -400,6 +421,7 @@ let bake ?baker : t -> t tzresult Lwt.t = in let* () = check_ai_launch_cycle_is_zero ~loc:__LOC__ block in let* state = State.apply_rewards ~baker:baker_name block state in + let current_cycle = Block.current_cycle previous_block in let new_future_current_cycle = Cycle.succ (Block.current_cycle block) in (* Dawn of a new cycle: apply cycle end operations *) let* state = @@ -425,9 +447,34 @@ let bake ?baker : t -> t tzresult Lwt.t = if state.force_attest_all then attest_all_ previous_block (block, state) else return (block, state) in - let* () = state.check_finalized_block (block, state) in + let* () = + List.iter_es + (fun f -> f metadata (block, state)) + state.check_finalized_block_perm + in + let* () = + List.iter_es + (fun f -> f metadata (block, state)) + state.check_finalized_block_temp + in + let state = + { + state with + check_finalized_block_temp = []; + previous_metadata = Some metadata; + grandparent = previous_block; + } + in return (block, state) +let finalize_block : (t_incr, t) scenarios = exec finalize_block_ + +(** Bake a block, with the given baker and the given operations. *) +let bake ?baker : t -> t tzresult Lwt.t = + fun input -> + let ( |=> ) = Lwt_result.bind in + finalize_payload_ ?baker input |=> finalize_block_ + let rec repeat n f acc = let open Lwt_result_syntax in if n <= 0 then return acc diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_base.ml b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_base.ml index 4352f9fd05c686f44ce941617488423fca3c51cd..79bbf05b7b734ef40e4ec531fb3ef9ae2b0e0300 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_base.ml +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_base.ml @@ -14,10 +14,14 @@ open State open Scenario_dsl open Log_helpers -(** Usual threaded state for the tests. Contains the current block, pending operations +(** Usual threaded state for the tests. Contains the current block and the known [State.t] *) type t = Block.t * State.t +(** Threaded state when constructing a block step by step in incremental mode. + The operation metadata list is built as operations are getting applied. *) +type t_incr = Incremental.t * State.t + let log ?(level = Cli.Logs.Info) ?color format = Format.kasprintf (fun s -> @@ -55,6 +59,11 @@ let exclude_bakers bakers : (t, t) scenarios = return {state with State.baking_policy = Some (Block.Excluding bakers_pkh)}) +let set_baked_round (round : int) : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + return {state with State.baking_policy = Some (Block.By_round round)}) + (** Unsets the baking policy, it returns to default ([By_round 0]) *) let unset_baking_policy : (t, t) scenarios = let open Lwt_result_syntax in @@ -299,3 +308,8 @@ let check_balance_fields ?(loc = __LOC__) src_name ~liquid ~staked src_name `Unstaked_finalizable unstaked_finalizable + +let with_metadata f (block, state) = + match state.previous_metadata with + | None -> assert false + | Some metadata -> f metadata (block, state) diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_begin.ml index 071ec85885677d322b9af1028a2dae27e47832f9..06e6d8ed339eb83439f7a759f9d775441cb6f6fc 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_begin.ml @@ -82,8 +82,8 @@ let init_constants ?(default = Test) ?(reward_per_block = 0L) (** Initialize the test, given some initial parameters *) let begin_test ?algo ?(burn_rewards = false) ?(force_attest_all = false) - ?(check_finalized_block = fun _ -> Lwt_result_syntax.return_unit) - delegates_name_list : (constants, t) scenarios = + ?(check_finalized_block_perm = []) delegates_name_list : + (constants, t) scenarios = exec (fun (constants : constants) -> let open Lwt_result_syntax in let bootstrap = "__bootstrap__" in @@ -152,8 +152,14 @@ let begin_test ?algo ?(burn_rewards = false) ?(force_attest_all = false) pending_slashes = []; double_signings = []; force_attest_all; - check_finalized_block; + check_finalized_block_perm; + check_finalized_block_temp = []; + previous_metadata = None; operation_mode = Bake; + (* The grandparent is only used to get the consensus key, so it is + fine to set it to Genesis here. If needed in the future, an option + type would be more appropriate. *) + grandparent = block; } in let* () = check_all_balances block state in diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_op.ml b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_op.ml index ecce91f405c31933c523f8b4f8a7636d7c5f8dfc..a4610cc125c7541b0384cbefee845c4dabfe13f0 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_op.ml +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/scenario_op.ml @@ -659,6 +659,10 @@ let make_denunciations ?single ?rev ?filter () = let add_account_with_funds ?algo name ~funder amount = add_account ?algo name --> transfer funder name amount --> reveal name +let start_payload : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_, state) -> return {state with State.operation_mode = Wait}) + let batch ~source : (t, t) scenarios = let open Lwt_result_syntax in exec_state (fun (_, state) -> diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/state.ml b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/state.ml index 8400df7022777872cf82c631e52b54119f266322..ec99172479a916c1a6c189be694202ffa02b9fb7 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/helpers/state.ml +++ b/src/proto_023_PtSeouLo/lib_protocol/test/helpers/state.ml @@ -37,8 +37,13 @@ type t = { (Signature.Public_key_hash.t * Protocol.Denunciations_repr.item) list; double_signings : double_signing_state list; force_attest_all : bool; - check_finalized_block : Block.t * t -> unit tzresult Lwt.t; + check_finalized_block_perm : + (Block.full_metadata -> Block.t * t -> unit tzresult Lwt.t) list; + check_finalized_block_temp : + (Block.full_metadata -> Block.t * t -> unit tzresult Lwt.t) list; + previous_metadata : Block.full_metadata option; operation_mode : operation_mode; + grandparent : Block.t; } (** Expected number of cycles before staking parameters get applied *) diff --git a/src/proto_023_PtSeouLo/lib_protocol/test/integration/consensus/test_companion_key.ml b/src/proto_023_PtSeouLo/lib_protocol/test/integration/consensus/test_companion_key.ml index 5106de6c55ee368ce325efc97066252651063183..e7b2f98aea9edeb160b0278d4ddacdaac2d83a9e 100644 --- a/src/proto_023_PtSeouLo/lib_protocol/test/integration/consensus/test_companion_key.ml +++ b/src/proto_023_PtSeouLo/lib_protocol/test/integration/consensus/test_companion_key.ml @@ -214,19 +214,19 @@ let test_simple_register_consensus_and_companion_keys = let consensus_rights_delay = Default_parameters.constants_mainnet.consensus_rights_delay in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in init_constants () --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> (Tag "is bootstrap" --> begin_test ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm (delegate :: bootstrap_accounts) |+ Tag "is created" --> begin_test ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm ~algo:Bls bootstrap_accounts --> add_account_with_funds @@ -329,7 +329,7 @@ let test_register_other_accounts_as_ck = --> set S.consensus_rights_delay consensus_rights_delay --> begin_test ~algo:Bls - ~check_finalized_block:check_all_cks + ~check_finalized_block_perm:[(fun _ -> check_all_cks)] ~force_attest_all:true ["delegate"; "victim_1"; "victim_2"] (* Both victims start with themselves as their own consensus_keys *) @@ -386,14 +386,14 @@ let test_self_register_as_companion = Default_parameters.constants_mainnet.consensus_rights_delay in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in init_constants () --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] (* As expected, a delegate cannot register itself as a companion, if it is already itself its own consensus key *) @@ -530,7 +530,7 @@ let test_register_same_key_multiple_times = in let delegate = "delegate" in let ck = "ck" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in let update_either_ck ~ck_name delegate = Tag "consensus" --> update_consensus_key ~ck_name delegate |+ Tag "companion" --> update_companion_key ~ck_name delegate @@ -596,7 +596,7 @@ let test_register_same_key_multiple_times = --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls ck --> update_either_ck ~ck_name:ck delegate @@ -617,7 +617,7 @@ let test_register_new_key_every_cycle = Default_parameters.constants_mainnet.consensus_rights_delay in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in let update_both_cks delegate = add_account "consensus_key" --> update_consensus_key ~ck_name:"consensus_key" delegate @@ -630,7 +630,7 @@ let test_register_new_key_every_cycle = --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> loop (consensus_rights_delay + 2) (update_both_cks delegate --> next_cycle) @@ -639,14 +639,14 @@ let test_register_key_end_of_cycle = Default_parameters.constants_mainnet.consensus_rights_delay in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in init_constants () --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls "ck" --> exec bake_until_next_cycle_end_but_one @@ -665,13 +665,13 @@ let test_register_key_end_of_cycle = let test_registration_override = let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in init_constants () --> set S.allow_tz4_delegate_enable true --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls "ck1" --> add_account ~algo:Bls "ck2" @@ -725,7 +725,7 @@ let test_in_registration_table_twice = This ensures that a key can be pending for two different cycles at the same time. *) let consensus_rights_delay = 4 in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in let check_is_pending_twice ~loc ~ck ~registered_for kind = let open Lwt_result_syntax in exec_unit (fun (block, state) -> @@ -771,7 +771,7 @@ let test_in_registration_table_twice = --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls "ck1" --> add_account ~algo:Bls "ck2" @@ -875,7 +875,7 @@ let test_fail_noop = Default_parameters.constants_mainnet.consensus_rights_delay in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in let assert_fail_with_invalid_consensus_key_update_noop kind = assert_failure ~loc:__LOC__ ~expected_error:(fun (_block, state) err -> let delegate = State.find_account delegate state in @@ -898,7 +898,7 @@ let test_fail_noop = init_constants () --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay - --> begin_test ~force_attest_all:true ~check_finalized_block [delegate] + --> begin_test ~force_attest_all:true ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls "ck" --> fold_tag (fun kind -> diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index df34be2c2649ec43ea212b7f7234fb14d388b3a0..f04560b00faf04c9fb19d6658229c87c674845ef 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -41,6 +41,8 @@ type t = { type block = t +type full_metadata = block_header_metadata * operation_receipt list + let get_alpha_ctxt b = let open Lwt_result_wrap_syntax in let*@ ctxt, _migration_balance_updates, _migration_operation_results = diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.mli b/src/proto_alpha/lib_protocol/test/helpers/block.mli index a703ec3ec13d48ec72f1d6ad882ba5b5feec7712..4315ccb8b8f66e441d511362f4785967de88a082 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/block.mli @@ -39,6 +39,8 @@ type t = { type block = t +type full_metadata = block_header_metadata * operation_receipt list + (** Not the same as [Context.get_alpha_ctxt] as it does not construct a new block *) val get_alpha_ctxt : t -> context tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/helpers/incremental.ml b/src/proto_alpha/lib_protocol/test/helpers/incremental.ml index 44d8ed58a0b290e44c8745467e695e7247291727..ad3732df75410dc9549155001e2b124249ee6965 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/incremental.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/incremental.ml @@ -47,6 +47,8 @@ let rev_operations {rev_operations; _} = rev_operations let rev_tickets {rev_tickets; _} = rev_tickets +let delegate {delegate; _} = delegate + let validation_state {state = vs, _; _} = vs let level st = st.header.shell.level diff --git a/src/proto_alpha/lib_protocol/test/helpers/incremental.mli b/src/proto_alpha/lib_protocol/test/helpers/incremental.mli index 301765a0721549fcb10ec704a1f623e705db2e77..9c813180a733d7eeca9d6b5d20199d2de18ea666 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/incremental.mli +++ b/src/proto_alpha/lib_protocol/test/helpers/incremental.mli @@ -38,6 +38,8 @@ val rev_operations : incremental -> Operation.packed list val rev_tickets : incremental -> operation_receipt list +val delegate : incremental -> Account.t + val validation_state : incremental -> validation_state val level : incremental -> int32 diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml index d191335c730a19ebc51238de2d819e26f1c009fa..98ecdaad3f9cfb3932e6e7aa70e5887ff3627442 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_bake.ml @@ -284,11 +284,20 @@ let check_ai_launch_cycle_is_zero ~loc block = Test.fail ~__LOC__:loc "AI launch cycle should always be zero" ; return_unit -(** Bake a block, with the given baker and the given operations. *) -let bake ?baker : t -> t tzresult Lwt.t = +(** Apply all operations pending in the [state]. + It is imperative that the list of pending operations in the state + is empty before finalizing the block, either manually, or by calling this function. *) +let apply_all_pending_operations_ : t_incr -> t_incr tzresult Lwt.t = + fun (i, state) -> + let open Lwt_result_wrap_syntax in + let state, operations = State.pop_pending_operations state in + let* i = List.fold_left_es Incremental.add_operation i operations in + return (i, state) + +(** finalize the payload of the next block. Can start including preattestations. *) +let finalize_payload_ ?payload_round ?baker : t -> t_incr tzresult Lwt.t = fun (block, state) -> let open Lwt_result_wrap_syntax in - let previous_block = block in let policy = match baker with | None -> state.baking_policy @@ -308,7 +317,6 @@ let bake ?baker : t -> t tzresult Lwt.t = let baker_name, {contract = baker_contract; _} = State.find_account_from_pkh baker state in - let current_cycle = Block.current_cycle block in let* level = Plugin.RPC.current_level Block.rpc_ctxt block in let* next_level = let* ctxt = Context.get_alpha_ctxt (B block) in @@ -327,16 +335,17 @@ let bake ?baker : t -> t tzresult Lwt.t = else Per_block_vote_pass in let* () = check_issuance_rpc block in - let state, operations = State.pop_pending_operations state in - let* block, state = - let* block', _metadata = - Block.bake_with_metadata ?policy ~adaptive_issuance_vote ~operations block - in + let* block' = Block.bake ?policy ~adaptive_issuance_vote block in + let* i = + Incremental.begin_construction + ?payload_round + ~payload:state.pending_operations + ?policy + ~adaptive_issuance_vote + block + in + let* i, state = if state.burn_rewards then - (* Incremental mode *) - let* i = - Incremental.begin_construction ?policy ~adaptive_issuance_vote block - in let* block_rewards = Context.get_issuance_per_minute (B block') in let ctxt = Incremental.alpha_ctxt i in let*@ context, _ = @@ -347,13 +356,26 @@ let bake ?baker : t -> t tzresult Lwt.t = block_rewards in let i = Incremental.set_alpha_ctxt i context in - let* i = List.fold_left_es Incremental.add_operation i operations in - let* block = Incremental.finalize_block i in let state = State.apply_burn block_rewards baker_name state in - return (block, state) - else return (block', state) + return (i, state) + else return (i, state) + in + apply_all_pending_operations_ (i, state) + +let finalize_payload ?payload_round ?baker () : (t, t_incr) scenarios = + exec (finalize_payload_ ?payload_round ?baker) + +let finalize_block_ : t_incr -> t tzresult Lwt.t = + fun (i, state) -> + let open Lwt_result_wrap_syntax in + assert (List.is_empty state.pending_operations) ; + let* block, block_metadata = Incremental.finalize_block_with_metadata i in + let ((_, op_metadata) as metadata) = + (block_metadata, List.rev (Incremental.rev_tickets i)) in - let baker_acc = State.find_account baker_name state in + let previous_block = Incremental.predecessor i in + let baker = Incremental.delegate i in + let baker_name, baker_acc = State.find_account_from_pkh baker.pkh state in (* update baker and attesters activity *) let update_activity delegate_account = Account_helpers.update_activity @@ -362,26 +384,25 @@ let bake ?baker : t -> t tzresult Lwt.t = (Block.current_cycle block) in let* attesters = - let open Tezos_raw_protocol_alpha.Alpha_context in - let* ctxt = Context.get_alpha_ctxt (B previous_block) in List.filter_map_es - (fun op -> - let ({protocol_data = Operation_data protocol_data; _} - : packed_operation) = - op - in - match protocol_data.contents with - | Single (Attestation {consensus_content; _}) -> - let*@ _, owner = - Stake_distribution.slot_owner - ctxt - (Level.from_raw ctxt consensus_content.level) - consensus_content.slot - in - return_some owner.delegate - | _ -> return_none) - operations + (function + | Protocol.Apply_results.No_operation_metadata -> return_none + | Operation_metadata {contents} -> ( + match contents with + | Single_result (Attestation_result {delegate; _}) + | Single_result (Preattestation_result {delegate; _}) -> + return_some [delegate] + | Single_result (Attestations_aggregate_result {committee; _}) + | Single_result (Preattestations_aggregate_result {committee; _}) -> + return_some + (List.map + (fun ((ck : Protocol.Alpha_context.Consensus_key.t), _) -> + ck.delegate) + committee) + | _ -> return_none)) + op_metadata in + let attesters = List.flatten attesters in let state = State.update_map ~f:(fun acc_map -> @@ -400,6 +421,7 @@ let bake ?baker : t -> t tzresult Lwt.t = in let* () = check_ai_launch_cycle_is_zero ~loc:__LOC__ block in let* state = State.apply_rewards ~baker:baker_name block state in + let current_cycle = Block.current_cycle previous_block in let new_future_current_cycle = Cycle.succ (Block.current_cycle block) in (* Dawn of a new cycle: apply cycle end operations *) let* state = @@ -425,9 +447,34 @@ let bake ?baker : t -> t tzresult Lwt.t = if state.force_attest_all then attest_all_ previous_block (block, state) else return (block, state) in - let* () = state.check_finalized_block (block, state) in + let* () = + List.iter_es + (fun f -> f metadata (block, state)) + state.check_finalized_block_perm + in + let* () = + List.iter_es + (fun f -> f metadata (block, state)) + state.check_finalized_block_temp + in + let state = + { + state with + check_finalized_block_temp = []; + previous_metadata = Some metadata; + grandparent = previous_block; + } + in return (block, state) +let finalize_block : (t_incr, t) scenarios = exec finalize_block_ + +(** Bake a block, with the given baker and the given operations. *) +let bake ?baker : t -> t tzresult Lwt.t = + fun input -> + let ( |=> ) = Lwt_result.bind in + finalize_payload_ ?baker input |=> finalize_block_ + let rec repeat n f acc = let open Lwt_result_syntax in if n <= 0 then return acc diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_base.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_base.ml index 4352f9fd05c686f44ce941617488423fca3c51cd..79bbf05b7b734ef40e4ec531fb3ef9ae2b0e0300 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_base.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_base.ml @@ -14,10 +14,14 @@ open State open Scenario_dsl open Log_helpers -(** Usual threaded state for the tests. Contains the current block, pending operations +(** Usual threaded state for the tests. Contains the current block and the known [State.t] *) type t = Block.t * State.t +(** Threaded state when constructing a block step by step in incremental mode. + The operation metadata list is built as operations are getting applied. *) +type t_incr = Incremental.t * State.t + let log ?(level = Cli.Logs.Info) ?color format = Format.kasprintf (fun s -> @@ -55,6 +59,11 @@ let exclude_bakers bakers : (t, t) scenarios = return {state with State.baking_policy = Some (Block.Excluding bakers_pkh)}) +let set_baked_round (round : int) : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_block, state) -> + return {state with State.baking_policy = Some (Block.By_round round)}) + (** Unsets the baking policy, it returns to default ([By_round 0]) *) let unset_baking_policy : (t, t) scenarios = let open Lwt_result_syntax in @@ -299,3 +308,8 @@ let check_balance_fields ?(loc = __LOC__) src_name ~liquid ~staked src_name `Unstaked_finalizable unstaked_finalizable + +let with_metadata f (block, state) = + match state.previous_metadata with + | None -> assert false + | Some metadata -> f metadata (block, state) diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml index 071ec85885677d322b9af1028a2dae27e47832f9..06e6d8ed339eb83439f7a759f9d775441cb6f6fc 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_begin.ml @@ -82,8 +82,8 @@ let init_constants ?(default = Test) ?(reward_per_block = 0L) (** Initialize the test, given some initial parameters *) let begin_test ?algo ?(burn_rewards = false) ?(force_attest_all = false) - ?(check_finalized_block = fun _ -> Lwt_result_syntax.return_unit) - delegates_name_list : (constants, t) scenarios = + ?(check_finalized_block_perm = []) delegates_name_list : + (constants, t) scenarios = exec (fun (constants : constants) -> let open Lwt_result_syntax in let bootstrap = "__bootstrap__" in @@ -152,8 +152,14 @@ let begin_test ?algo ?(burn_rewards = false) ?(force_attest_all = false) pending_slashes = []; double_signings = []; force_attest_all; - check_finalized_block; + check_finalized_block_perm; + check_finalized_block_temp = []; + previous_metadata = None; operation_mode = Bake; + (* The grandparent is only used to get the consensus key, so it is + fine to set it to Genesis here. If needed in the future, an option + type would be more appropriate. *) + grandparent = block; } in let* () = check_all_balances block state in diff --git a/src/proto_alpha/lib_protocol/test/helpers/scenario_op.ml b/src/proto_alpha/lib_protocol/test/helpers/scenario_op.ml index ecce91f405c31933c523f8b4f8a7636d7c5f8dfc..a4610cc125c7541b0384cbefee845c4dabfe13f0 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/scenario_op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/scenario_op.ml @@ -659,6 +659,10 @@ let make_denunciations ?single ?rev ?filter () = let add_account_with_funds ?algo name ~funder amount = add_account ?algo name --> transfer funder name amount --> reveal name +let start_payload : (t, t) scenarios = + let open Lwt_result_syntax in + exec_state (fun (_, state) -> return {state with State.operation_mode = Wait}) + let batch ~source : (t, t) scenarios = let open Lwt_result_syntax in exec_state (fun (_, state) -> diff --git a/src/proto_alpha/lib_protocol/test/helpers/state.ml b/src/proto_alpha/lib_protocol/test/helpers/state.ml index 8400df7022777872cf82c631e52b54119f266322..ec99172479a916c1a6c189be694202ffa02b9fb7 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/state.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/state.ml @@ -37,8 +37,13 @@ type t = { (Signature.Public_key_hash.t * Protocol.Denunciations_repr.item) list; double_signings : double_signing_state list; force_attest_all : bool; - check_finalized_block : Block.t * t -> unit tzresult Lwt.t; + check_finalized_block_perm : + (Block.full_metadata -> Block.t * t -> unit tzresult Lwt.t) list; + check_finalized_block_temp : + (Block.full_metadata -> Block.t * t -> unit tzresult Lwt.t) list; + previous_metadata : Block.full_metadata option; operation_mode : operation_mode; + grandparent : Block.t; } (** Expected number of cycles before staking parameters get applied *) diff --git a/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml b/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml index d91328dfa8138c09a31bc9311c067ab88bf24f94..4d7c9959891dcddeaaa988e825060ed8858e4942 100644 --- a/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml +++ b/src/proto_alpha/lib_protocol/test/integration/consensus/test_companion_key.ml @@ -214,19 +214,19 @@ let test_simple_register_consensus_and_companion_keys = let consensus_rights_delay = Default_parameters.constants_mainnet.consensus_rights_delay in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in init_constants () --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> (Tag "is bootstrap" --> begin_test ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm (delegate :: bootstrap_accounts) |+ Tag "is created" --> begin_test ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm ~algo:Bls bootstrap_accounts --> add_account_with_funds @@ -329,7 +329,7 @@ let test_register_other_accounts_as_ck = --> set S.consensus_rights_delay consensus_rights_delay --> begin_test ~algo:Bls - ~check_finalized_block:check_all_cks + ~check_finalized_block_perm:[(fun _ -> check_all_cks)] ~force_attest_all:true ["delegate"; "victim_1"; "victim_2"] (* Both victims start with themselves as their own consensus_keys *) @@ -386,14 +386,14 @@ let test_self_register_as_companion = Default_parameters.constants_mainnet.consensus_rights_delay in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in init_constants () --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] (* As expected, a delegate cannot register itself as a companion, if it is already itself its own consensus key *) @@ -530,7 +530,7 @@ let test_register_same_key_multiple_times = in let delegate = "delegate" in let ck = "ck" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in let update_either_ck ~ck_name delegate = Tag "consensus" --> update_consensus_key ~ck_name delegate |+ Tag "companion" --> update_companion_key ~ck_name delegate @@ -596,7 +596,7 @@ let test_register_same_key_multiple_times = --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls ck --> update_either_ck ~ck_name:ck delegate @@ -617,7 +617,7 @@ let test_register_new_key_every_cycle = Default_parameters.constants_mainnet.consensus_rights_delay in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in let update_both_cks delegate = add_account "consensus_key" --> update_consensus_key ~ck_name:"consensus_key" delegate @@ -630,7 +630,7 @@ let test_register_new_key_every_cycle = --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> loop (consensus_rights_delay + 2) (update_both_cks delegate --> next_cycle) @@ -639,14 +639,14 @@ let test_register_key_end_of_cycle = Default_parameters.constants_mainnet.consensus_rights_delay in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in init_constants () --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls "ck" --> exec bake_until_next_cycle_end_but_one @@ -665,13 +665,13 @@ let test_register_key_end_of_cycle = let test_registration_override = let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in init_constants () --> set S.allow_tz4_delegate_enable true --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls "ck1" --> add_account ~algo:Bls "ck2" @@ -725,7 +725,7 @@ let test_in_registration_table_twice = This ensures that a key can be pending for two different cycles at the same time. *) let consensus_rights_delay = 4 in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in let check_is_pending_twice ~loc ~ck ~registered_for kind = let open Lwt_result_syntax in exec_unit (fun (block, state) -> @@ -771,7 +771,7 @@ let test_in_registration_table_twice = --> begin_test ~algo:Bls ~force_attest_all:true - ~check_finalized_block + ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls "ck1" --> add_account ~algo:Bls "ck2" @@ -875,7 +875,7 @@ let test_fail_noop = Default_parameters.constants_mainnet.consensus_rights_delay in let delegate = "delegate" in - let check_finalized_block = check_cks delegate in + let check_finalized_block_perm = [(fun _ -> check_cks delegate)] in let assert_fail_with_invalid_consensus_key_update_noop kind = assert_failure ~loc:__LOC__ ~expected_error:(fun (_block, state) err -> let delegate = State.find_account delegate state in @@ -898,7 +898,7 @@ let test_fail_noop = init_constants () --> set S.allow_tz4_delegate_enable true --> set S.consensus_rights_delay consensus_rights_delay - --> begin_test ~force_attest_all:true ~check_finalized_block [delegate] + --> begin_test ~force_attest_all:true ~check_finalized_block_perm [delegate] --> add_account ~algo:Bls "ck" --> fold_tag (fun kind ->