diff --git a/tezt/lib_tezos/agnostic_baker.ml b/tezt/lib_tezos/agnostic_baker.ml index 64f90ccc0ddbd777072537e60f660ed93b843061..ab8693674a11d0f56e94ee6e6408bb705066e131 100644 --- a/tezt/lib_tezos/agnostic_baker.ml +++ b/tezt/lib_tezos/agnostic_baker.ml @@ -251,3 +251,20 @@ let init ?runner ?(path = Uses.path Constant.octez_experimental_agnostic_baker) let* () = run ?event_level ?event_sections_levels agnostic_baker in let* () = wait_for_ready agnostic_baker in return agnostic_baker + +(** Logging helpers for baker events. *) + +let log_block_injection ?color baker = + on_event baker (fun event -> + if String.equal event.name "block_injected.v0" then + let open JSON in + let level = event.value |-> "level" |> as_int in + let round = event.value |-> "round" |> as_int in + let delegate = event.value |-> "delegate" |-> "alias" |> as_string in + Log.info + ?color + "[%s] Block injected at level %d round %d for %s." + (name baker) + level + round + delegate) diff --git a/tezt/lib_tezos/agnostic_baker.mli b/tezt/lib_tezos/agnostic_baker.mli index 6562792dbd929eb52a3cf5b6c2db90b7a03441f5..1ee9d43483a24b5127d087bb6c479e86d8314d4d 100644 --- a/tezt/lib_tezos/agnostic_baker.mli +++ b/tezt/lib_tezos/agnostic_baker.mli @@ -222,3 +222,13 @@ val init : Node.t -> Client.t -> t Lwt.t + +(** Log block injection events. + + Show the baker daemon name, level and round of the block, and + delegate for which it was injected. + + This log is relatively lightweight and a good indicator of chain + progress during a test. It can also be useful to observe baking + rights at the levels and rounds featured in a test. *) +val log_block_injection : ?color:Log.Color.t -> t -> unit diff --git a/tezt/tests/dal.ml b/tezt/tests/dal.ml index 65ac5c5f7f90121dc97932aa0e50f028793fdfb5..89f2c2c21013cf969c468b07153ffe43341a6e28 100644 --- a/tezt/tests/dal.ml +++ b/tezt/tests/dal.ml @@ -4625,13 +4625,10 @@ let test_migration_accuser_issue ~migrate_from ~migrate_to = client in Log.info "Start bakers for the current and the next protocols" ; - let baker_from = - Baker.create ~dal_node ~protocol:migrate_from node client - in - let baker_to = Baker.create ~dal_node ~protocol:migrate_to node client in - let* () = Baker.run baker_from in - let* () = Baker.run baker_to in + let baker = Agnostic_baker.create ~dal_node node client in + + let* () = Agnostic_baker.run baker in let* _level = Node.wait_for_level node migration_level in Log.info "migrated to next protocol, starting a second DAL node accuser" ; @@ -4646,8 +4643,7 @@ let test_migration_accuser_issue ~migrate_from ~migrate_to = let* () = Dal_node.run accuser ~wait_ready:true in let* _level = Node.wait_for_level node last_level in - let* () = Baker.terminate baker_from in - let* () = Baker.terminate baker_to in + let* () = Agnostic_baker.terminate baker in Lwt_list.iter_s (fun delegate -> @@ -4671,7 +4667,7 @@ let test_migration_accuser_issue ~migrate_from ~migrate_to = ~scenario ~tags ~description - ~uses:[Protocol.baker migrate_from; Protocol.baker migrate_to] + ~uses:[Constant.octez_experimental_agnostic_baker] ~activation_timestamp:Now ~producer_profiles:[slot_index] ~minimal_block_delay: diff --git a/tezt/tests/protocol_migration.ml b/tezt/tests/protocol_migration.ml index b4cd5c8771edbafca3401af9adafa80d7e4c714d..e69728f1e692f85867fc95be2c244f9afc62a85c 100644 --- a/tezt/tests/protocol_migration.ml +++ b/tezt/tests/protocol_migration.ml @@ -457,11 +457,11 @@ let start_protocol ?consensus_threshold ?round_duration ~parameter_file client -(** Test that migration occuring through baker daemons +(** Test that migration occuring through (agnostic) baker daemons - does not halt the chain; - and that the migration block is not attested by the newer - protocol's baker. + protocol's baker (if not using agnostic baker). This has become an issue of sort after updating the consensus protocol to Tenderbake. For one, attestations have become mandatory, and not only a sign @@ -472,27 +472,34 @@ let start_protocol ?consensus_threshold ?round_duration Revisit this test, as it may start to fail, whenever a new (family of) consensus protocol is put into place in Tezos. **) let test_migration_with_bakers ?(migration_level = 4) - ?(num_blocks_post_migration = 5) ~migrate_from ~migrate_to () = + ?(num_blocks_post_migration = 5) ~migrate_from ~migrate_to + ~use_agnostic_baker () = + let baker_string, uses = + if use_agnostic_baker then + ("agnostic_baker", [Constant.octez_experimental_agnostic_baker]) + else ("baker", [Protocol.baker migrate_from; Protocol.baker migrate_to]) + in Test.register ~__FILE__ ~title: (Printf.sprintf - "chain progress/attestation of migration block from %s to %s with \ - baker daemons" + "chain progress/attestation of migration block from %s to %s with %s \ + daemon(s)" (Protocol.tag migrate_from) - (Protocol.tag migrate_to)) + (Protocol.tag migrate_to) + baker_string) ~tags: [ team; "protocol"; "migration"; - "baker"; + baker_string; "attesting"; "metadata"; "from_" ^ Protocol.tag migrate_from; "to_" ^ Protocol.tag migrate_to; ] - ~uses:[Protocol.baker migrate_from; Protocol.baker migrate_to] + ~uses @@ fun () -> let* client, node = user_migratable_node_init ~migration_level ~migrate_to () @@ -506,23 +513,33 @@ let test_migration_with_bakers ?(migration_level = 4) let* () = check_adaptive_issuance_launch_cycle ~loc:__LOC__ ~migrate_from client in + let delegates = + List.map + (fun account -> account.Account.alias) + (Array.to_list Account.Bootstrap.keys) + in - Log.info - "Launching 2 bakers, one for %s (pre-migration protocol), one for \ - %s(post-migration protocol)" - (Protocol.name migrate_from) - (Protocol.name migrate_to) ; - let baker_for_proto protocol = - let name = Printf.sprintf "baker-proto-%s" (Protocol.name protocol) in - let delegates = - List.map - (fun account -> account.Account.alias) - (Array.to_list Account.Bootstrap.keys) - in - Baker.init ~protocol ~name node client ~delegates + let* () = + if use_agnostic_baker then ( + Log.info "Launching agnostic baker" ; + let* _agnostic_baker = + Agnostic_baker.init ~name:"agnostic_baker" node client ~delegates + in + unit) + else ( + Log.info + "Launching 2 bakers, one for %s (pre-migration protocol), one for \ + %s(post-migration protocol)" + (Protocol.name migrate_from) + (Protocol.name migrate_to) ; + let baker_for_proto protocol = + let name = Printf.sprintf "baker-proto-%s" (Protocol.name protocol) in + Baker.init ~protocol ~name node client ~delegates + in + let* _baker_from_proto = baker_for_proto migrate_from in + let* _baker_to_proto = baker_for_proto migrate_to in + unit) in - let* _baker_from_proto = baker_for_proto migrate_from in - let* _baker_to_proto = baker_for_proto migrate_to in let* _ret = Node.wait_for_level node migration_level in let* () = check_adaptive_issuance_launch_cycle ~loc:__LOC__ ~migrate_from client @@ -594,14 +611,14 @@ let test_forked_migration_manual ?(migration_level = 4) team; "protocol"; "migration"; - "baker"; + "agnostic_baker"; "attesting"; "fork"; "manual"; "from_" ^ Protocol.tag migrate_from; "to_" ^ Protocol.tag migrate_to; ] - ~uses:[Protocol.baker migrate_to] + ~uses:[Constant.octez_experimental_agnostic_baker] ~title: (Printf.sprintf "manually forked migration blocks from %s to %s" @@ -724,36 +741,14 @@ let test_forked_migration_manual ?(migration_level = 4) "proposer %L is the same as proposer %R: only one migration block has \ been proposed") ; - let baker_for_proto ~delegates ~node ~client ~protocol = - let name = - Printf.sprintf - "baker-proto-%s-on-%s" - (Protocol.name protocol) - (Node.name node) - in - Baker.init ~protocol ~name node client ~delegates - in - Log.info "Reconnecting nodes and launching bakers for %s" (Protocol.name migrate_to) ; let* () = connect cn1 cn2 in - let* baker_1 = - baker_for_proto - ~delegates:delegates_1 - ~node:node_1 - ~client:client_1 - ~protocol:migrate_to - in + let* baker_1 = Agnostic_baker.init ~delegates:delegates_1 node_1 client_1 in - let* baker_2 = - baker_for_proto - ~delegates:delegates_2 - ~node:node_2 - ~client:client_2 - ~protocol:migrate_to - in + let* baker_2 = Agnostic_baker.init ~delegates:delegates_2 node_2 client_2 in let until_level = migration_level + num_blocks_post_migration in Log.info "Waiting to reach level %d" until_level ; @@ -762,8 +757,8 @@ let test_forked_migration_manual ?(migration_level = 4) check_adaptive_issuance_launch_cycle ~loc:__LOC__ ~migrate_from client_1 in - let* () = Baker.terminate baker_1 in - let* () = Baker.terminate baker_2 in + let* () = Agnostic_baker.terminate baker_1 in + let* () = Agnostic_baker.terminate baker_2 in unit (** Wait for a quorum event on a proposal at the given [level]. @@ -773,11 +768,28 @@ let test_forked_migration_manual ?(migration_level = 4) "qc_reached". This is because there is little time between both events, so there would be a risk that "qc_reached" happens before the second waiter has been registered. *) -let wait_for_qc_at_level level baker = +let wait_for_qc_at_level : + type baker. + wait_for: + (?where:string -> + baker -> + string -> + (JSON.t -> unit option) -> + unit Lwt.t) -> + int -> + baker -> + unit Lwt.t = + fun ~wait_for level baker -> + Log.info + "Wait for a quorum event on a proposal at pre-migration level %d. At this \ + point, we know that attestations on this proposal have been propagated, \ + so everyone will be able to progress to the next level even if the \ + network gets split." + level ; let where = sf "level = %d" level in let level_seen = ref false in let proposal_waiter = - Baker.wait_for baker "new_valid_proposal.v0" ~where (fun json -> + wait_for baker "new_valid_proposal.v0" ~where (fun json -> let proposal_level = JSON.(json |-> "level" |> as_int) in if proposal_level = level then ( level_seen := true ; @@ -790,7 +802,7 @@ let wait_for_qc_at_level level baker = else None) in Background.register proposal_waiter ; - Baker.wait_for baker "qc_reached.v0" ~where (fun (_ : JSON.t) -> + wait_for baker "qc_reached.v0" ~where (fun (_ : JSON.t) -> if !level_seen then Some () else None) let get_block_at_level level client = @@ -798,24 +810,61 @@ let get_block_at_level level client = client (RPC.get_chain_block ~version:"1" ~block:(string_of_int level) ()) -let test_forked_migration_bakers ~migrate_from ~migrate_to = +let wait_for_post_migration_proposal : + type baker. + wait_for: + (?where:string -> + baker -> + string -> + (JSON.t -> unit option) -> + unit Lwt.t) -> + int -> + baker -> + unit Lwt.t = + fun ~wait_for post_migration_level baker -> + wait_for baker "new_valid_proposal.v0" (fun json -> + let level = JSON.(json |-> "level" |> as_int) in + if level = post_migration_level then Some () + else if level > post_migration_level then + Test.fail "Reached level %d with a split network." level + else None) + +let test_forked_migration_bakers bakers ~migrate_from ~migrate_to = + let baker_name, baker_tags, baker_uses = + match bakers with + | `Bakers -> + ( "baker", + ["baker"], + [Protocol.baker migrate_from; Protocol.baker migrate_to] ) + | `Agnostic_bakers -> + ( "agnostic baker", + ["agnostic_baker"], + [Constant.octez_experimental_agnostic_baker] ) + | `Mixed -> + ( "baker and agnostic baker", + ["baker"; "agnostic_baker"], + [ + Protocol.baker migrate_from; + Protocol.baker migrate_to; + Constant.octez_experimental_agnostic_baker; + ] ) + in Test.register ~__FILE__ ~tags: - [ - team; - "protocol"; - "migration"; - "baker"; - "attesting"; - "fork"; - "from_" ^ Protocol.tag migrate_from; - "to_" ^ Protocol.tag migrate_to; - ] - ~uses:[Protocol.baker migrate_from; Protocol.baker migrate_to] + ([team; "protocol"; "migration"] + @ baker_tags + @ [ + "attesting"; + "fork"; + "from_" ^ Protocol.tag migrate_from; + "to_" ^ Protocol.tag migrate_to; + ]) + ~uses:baker_uses ~title: (Printf.sprintf - "baker forked migration blocks from %s to %s" + "%s forked migration blocks from %s to %s" + baker_name (Protocol.tag migrate_from) (Protocol.tag migrate_to)) @@ fun () -> @@ -849,7 +898,8 @@ let test_forked_migration_bakers ~migrate_from ~migrate_to = Log.info "Partition bootstrap delegates into 3 groups. Start bakers for pre- and \ - post-migration protocols, on a separate node for each group of delegates." ; + post-migration protocols or agnostic bakers, on a separate node for each \ + group of delegates." ; (* The groups are chosen considering baker rights at levels 4 and 5, see comment further below. *) let group1 = @@ -878,18 +928,20 @@ let test_forked_migration_bakers ~migrate_from ~migrate_to = Baker.log_block_injection ~color:Log.Color.FG.yellow baker ; return baker in - let* baker1_from = baker_for_proto migrate_from group1 - and* _baker2_from = baker_for_proto migrate_from group2 - and* _baker3_from = baker_for_proto migrate_from group3 - and* baker1_to = baker_for_proto migrate_to group1 - and* _baker2_to = baker_for_proto migrate_to group2 - and* baker3_to = baker_for_proto migrate_to group3 in - Log.info - "Activate a protocol where everyone needs to sign off a block proposal for \ - it to be included, ie. set consensus_threshold to 100%% of \ - consensus_committee_size." ; - let* () = + let agnostic_baker (node, client, delegates) = + let name = sf "agnostic_baker_%s" (Node.name node) in + Log.info "Start %s for %a." name pp_delegates delegates ; + let* baker = Agnostic_baker.init ~name ~delegates node client in + Agnostic_baker.log_block_injection ~color:Log.Color.FG.yellow baker ; + return baker + in + + let start_protocol () = + Log.info + "Activate a protocol where everyone needs to sign off a block proposal \ + for it to be included, ie. set consensus_threshold to 100%% of \ + consensus_committee_size." ; start_protocol ~consensus_threshold:(fun ~consensus_committee_size -> consensus_committee_size) @@ -902,57 +954,157 @@ let test_forked_migration_bakers ~migrate_from ~migrate_to = ~protocol:migrate_from client1 in - let* () = - check_adaptive_issuance_launch_cycle ~loc:__LOC__ ~migrate_from client1 + let pre_migration_level = migration_level - 1 in + let post_migration_level = migration_level + 1 in + + let disconnect_clusters () = + Log.info + "Disconnect node3. There are now two independent clusters that don't \ + communicate: [node1; node2] and [node3]." ; + let* () = disconnect cn1 cn3 and* () = disconnect cn2 cn3 in + unit in - let pre_migration_level = migration_level - 1 in - Log.info - "Wait for a quorum event on a proposal at pre-migration level %d. At this \ - point, we know that attestations on this proposal have been propagated, \ - so everyone will be able to progress to the next level even if the \ - network gets split." - pre_migration_level ; - let* () = wait_for_qc_at_level pre_migration_level baker1_from in + let check_post_migration_proposal ~wait_for = + Log.info + "Migration blocks are not attested, so each cluster should be able to \ + propose blocks for the post-migration level %d. However, since none of \ + the clusters has enough voting power to reach the consensus_threshold, \ + they should not be able to propose blocks for higher levels.\n\ + We wait for each cluster to propose a block at the post-migration \ + level. (If this takes more than 10 seconds, check the comment on baking \ + rights in the code.)" + post_migration_level ; + (* For this step to be reasonably fast, we need both clusters to + have delegates with baking rights for early rounds at the + migration and post-migration levels. As of March 2023, this step + takes less than 4 seconds with the following baking rights (with + minimal_block_delay set to the default ie 1 second): + - level 4 (migration level), round 0: bootstrap3 (node3) + - level 4, round 1: bootstrap1 (node1) + - level 5, round 0: bootstrap1 (node1) + - level 5, round 1: bootstrap4 (node3) + If this step takes significantly longer to complete, check + whether the baking rights have changed and reorganize the split + of delegates into bakers as needed. *) + let* () = wait_for () in + Log.info "Post-migration proposal seen in both clusters." ; + unit + in - Log.info - "Disconnect node3. There are now two independent clusters that don't \ - communicate: [node1; node2] and [node3]." ; - let* () = disconnect cn1 cn3 and* () = disconnect cn2 cn3 in + let* () = + match bakers with + | `Bakers -> + let* baker1_from = baker_for_proto migrate_from group1 + and* _baker2_from = baker_for_proto migrate_from group2 + and* _baker3_from = baker_for_proto migrate_from group3 + and* baker1_to = baker_for_proto migrate_to group1 + and* _baker2_to = baker_for_proto migrate_to group2 + and* baker3_to = baker_for_proto migrate_to group3 in + + let* () = start_protocol () in + let* () = + check_adaptive_issuance_launch_cycle + ~loc:__LOC__ + ~migrate_from + client1 + in + let* () = + wait_for_qc_at_level + pre_migration_level + ~wait_for:Baker.wait_for + baker1_from + in + let* () = disconnect_clusters () in - let post_migration_level = migration_level + 1 in - Log.info - "Migration blocks are not attested, so each cluster should be able to \ - propose blocks for the post-migration level %d. However, since none of \ - the clusters has enough voting power to reach the consensus_threshold, \ - they should not be able to propose blocks for higher levels.\n\ - We wait for each cluster to propose a block at the post-migration level. \ - (If this takes more than 10 seconds, check the comment on baking rights \ - in the code.)" - post_migration_level ; - (* For this step to be reasonably fast, we need both clusters to - have delegates with baking rights for early rounds at the - migration and post-migration levels. As of March 2023, this step - takes less than 4 seconds with the following baking rights (with - minimal_block_delay set to the default ie 1 second): - - level 4 (migration level), round 0: bootstrap3 (node3) - - level 4, round 1: bootstrap1 (node1) - - level 5, round 0: bootstrap1 (node1) - - level 5, round 1: bootstrap4 (node3) - If this step takes significantly longer to complete, check - whether the baking rights have changed and reorganize the split - of delegates into bakers as needed. *) - let wait_for_post_migration_proposal baker = - Baker.wait_for baker "new_valid_proposal.v0" (fun json -> - let level = JSON.(json |-> "level" |> as_int) in - if level = post_migration_level then Some () - else if level > post_migration_level then - Test.fail "Reached level %d with a split network." level - else None) + let wait_for () = + let* () = + wait_for_post_migration_proposal + post_migration_level + ~wait_for:Baker.wait_for + baker1_to + and* () = + wait_for_post_migration_proposal + post_migration_level + ~wait_for:Baker.wait_for + baker3_to + in + unit + in + check_post_migration_proposal ~wait_for + | `Agnostic_bakers -> + let* agnostic_baker1 = agnostic_baker group1 + and* _agnostic_baker2 = agnostic_baker group2 + and* agnostic_baker3 = agnostic_baker group3 in + + let* () = start_protocol () in + let* () = + check_adaptive_issuance_launch_cycle + ~loc:__LOC__ + ~migrate_from + client1 + in + let* () = + wait_for_qc_at_level + pre_migration_level + ~wait_for:Agnostic_baker.wait_for + agnostic_baker1 + in + let* () = disconnect_clusters () in + + let wait_for () = + let* () = + wait_for_post_migration_proposal + post_migration_level + ~wait_for:Agnostic_baker.wait_for + agnostic_baker1 + and* () = + wait_for_post_migration_proposal + post_migration_level + ~wait_for:Agnostic_baker.wait_for + agnostic_baker3 + in + unit + in + check_post_migration_proposal ~wait_for + | `Mixed -> + let* baker1_from = baker_for_proto migrate_from group1 + and* baker1_to = baker_for_proto migrate_to group1 + and* _agnostic_baker2 = agnostic_baker group2 + and* agnostic_baker3 = agnostic_baker group3 in + + let* () = start_protocol () in + let* () = + check_adaptive_issuance_launch_cycle + ~loc:__LOC__ + ~migrate_from + client1 + in + let* () = + wait_for_qc_at_level + pre_migration_level + ~wait_for:Baker.wait_for + baker1_from + in + let* () = disconnect_clusters () in + + let wait_for () = + let* () = + wait_for_post_migration_proposal + post_migration_level + ~wait_for:Baker.wait_for + baker1_to + and* () = + wait_for_post_migration_proposal + post_migration_level + ~wait_for:Agnostic_baker.wait_for + agnostic_baker3 + in + unit + in + check_post_migration_proposal ~wait_for in - let* () = wait_for_post_migration_proposal baker1_to - and* () = wait_for_post_migration_proposal baker3_to in - Log.info "Post-migration proposal seen in both clusters." ; + let* () = check_adaptive_issuance_launch_cycle ~loc:__LOC__ ~migrate_from client1 in @@ -1766,8 +1918,19 @@ let test_unstaked_requests_and_min_delegated () = let register ~migrate_from ~migrate_to = test_migration_for_whole_cycle ~migrate_from ~migrate_to ; - test_migration_with_bakers ~migrate_from ~migrate_to () ; - test_forked_migration_bakers ~migrate_from ~migrate_to ; + test_migration_with_bakers + ~migrate_from + ~migrate_to + ~use_agnostic_baker:false + () ; + test_migration_with_bakers + ~migrate_from + ~migrate_to + ~use_agnostic_baker:true + () ; + List.iter + (test_forked_migration_bakers ~migrate_from ~migrate_to) + [`Bakers; `Agnostic_bakers; `Mixed] ; test_forked_migration_manual ~migrate_from ~migrate_to () ; test_migration_with_snapshots ~migrate_from ~migrate_to ; test_tolerated_inactivity_period () ; diff --git a/tezt/tests/voting.ml b/tezt/tests/voting.ml index d8abfc11e0482a14368b13278a93b3922e96e7ce..312e3a09bdfbfac8ef9a1f87f2760536fdff1aee 100644 --- a/tezt/tests/voting.ml +++ b/tezt/tests/voting.ml @@ -891,11 +891,7 @@ let test_user_activated_protocol_override_baker_vote ~from_protocol ~to_protocol "to_" ^ Protocol.tag to_protocol; ] ~uses: - [ - Protocol.accuser to_protocol; - Protocol.baker from_protocol; - Protocol.baker to_protocol; - ] + [Protocol.accuser to_protocol; Constant.octez_experimental_agnostic_baker] @@ fun () -> let node_arguments = [Node.Synchronisation_threshold 0] in let to_protocol_hash = Protocol.hash to_protocol in @@ -1226,11 +1222,7 @@ let test_user_activated_protocol_override_baker_vote ~from_protocol ~to_protocol Node.wait_for_level node (expected_level_of_next_proposal + good_measure) in - let* _ = Baker.init ~protocol:from_protocol node client in - - (* The baker for [to_protocol] is not ready until that protocol - activates, therefore we do not resolve yet. *) - let _to_protocol_baker_p = Baker.init ~protocol:to_protocol node client in + let* _ = Agnostic_baker.init node client in (* We also start an accuser for the [to_protocol] protocol. After the protocol switch, we verify that it starts registering blocks. *) @@ -1330,9 +1322,6 @@ let test_user_activated_protocol_override_baker_vote ~from_protocol ~to_protocol expected_level_of_next_proposal ; let* (_ : int) = wait_for_next_proposal_p in - Log.info "Activate the replacement protocol baker" ; - let* _ = _to_protocol_baker_p in - Log.info "Check that replacement protocol %s is active" (Protocol.hash to_protocol) ;