From b4192977ae773f527b7eb42d2b8721c8134d2876 Mon Sep 17 00:00:00 2001 From: Adam Allombert-Goget Date: Fri, 4 Apr 2025 11:22:33 +0200 Subject: [PATCH 1/4] tezt: add test for prequorum progress in baker_test --- tezt/tests/baker_test.ml | 120 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/tezt/tests/baker_test.ml b/tezt/tests/baker_test.ml index 454145679020..d891410b9f5f 100644 --- a/tezt/tests/baker_test.ml +++ b/tezt/tests/baker_test.ml @@ -633,6 +633,123 @@ let simple_attestations_aggregation = let () = check_aggregate ~expected_committee aggregate_json in unit +let prequorum_check_levels = + Protocol.register_test + ~__FILE__ + ~title:"prequorum monitoring check operations level" + ~tags:[team; "prequorum"; "monitoring"; "check"] + ~uses:(fun _protocol -> [Constant.octez_agnostic_baker]) + @@ fun protocol -> + let parameter_file = + Protocol.parameter_file ~constants:Constants_mainnet protocol + in + (* Using custom constants to make the test run faster *) + let* parameter_file = + Protocol.write_parameter_file + ~base:(Left parameter_file) + [(["minimal_block_delay"], `String "4")] + in + let* node, client = + Client.init_with_protocol + `Client + ~protocol + ~parameter_file + ~timestamp:Now + () + in + let* _ = Node.wait_for_level node 1 in + let delegate = Constant.bootstrap1 in + let public_key_hashes = + List.map (fun (account : Account.key) -> account.public_key_hash) + in + let* baker = + Agnostic_baker.init + ~event_level:`Debug + ~delegates:[Constant.activator.public_key_hash] + node + client + in + Agnostic_baker.log_events ~max_length:1000 baker ; + let* () = + Client.bake_for_and_wait + ~node + ~keys:(public_key_hashes Constant.all_secret_keys) + ~count:3 + client + in + let* current_level = Node.get_level node in + let previous_level = current_level - 1 in + let next_level = current_level + 1 in + let* block_payload_hash = + let* json = Client.RPC.call client @@ RPC.get_chain_block_header () in + return @@ JSON.(json |-> "payload_hash" |> as_string) + in + let preattest_for level = + let* slots = Operation.Consensus.get_slots ~level client in + let slot = Operation.Consensus.first_slot ~slots delegate in + let preattestation = + Operation.Consensus.preattestation + ~slot + ~level + ~block_payload_hash + ~round:0 + in + let* _ = + Operation.Consensus.inject + ~protocol + ~signer:delegate + preattestation + client + in + unit + in + let wait_for_preattestations_received () = + Agnostic_baker.wait_for + baker + "preattestations_received.v0" + JSON.( + fun json -> + let count = json |-> "count" |> as_int in + let delta = json |-> "delta_power" |> as_int in + let voting_power = json |-> "voting_power" |> as_int in + let preattestations = json |-> "preattestations" |> as_int in + Some (count, delta, voting_power, preattestations)) + in + Log.info "Injecting a preattestation for level %d round 0" current_level ; + (* Listen for the next preattestations_received event and inject a + preattestation for the current level. The preattestation is expected to be + accounted in the prequorum monitoring. *) + let waiter = wait_for_preattestations_received () in + let* () = preattest_for current_level in + let* count, delta, voting_power, preattestations = waiter in + if count <> 1 || delta = 0 || voting_power = 0 || preattestations <> 1 then + Test.fail "Prequorum is expected to progress" ; + Log.info "Injecting a preattestation for level %d round 0" previous_level ; + (* Same process but we inject a preattestation for the previous level. This + time, the preattestation is not expected to be accounted in the prequorum + monitoring. *) + let waiter = wait_for_preattestations_received () in + let* () = preattest_for previous_level in + let* count, delta', voting_power', preattestations' = waiter in + if + count <> 0 || delta' <> 0 + || voting_power <> voting_power' + || preattestations <> preattestations' + then Test.fail "Prequorum is not expected to progress" ; + Log.info "Injecting a preattestation for level %d round 0" next_level ; + (* Same for next level. Again, the preattestation is not expected to be + accounted in the prequorum monitoring. *) + let waiter = wait_for_preattestations_received () in + let* () = preattest_for next_level in + let* count, delta', voting_power', preattestations' = waiter in + if + count <> 0 || delta' <> 0 + || voting_power <> voting_power' + || preattestations <> preattestations' + then Test.fail "Prequorum is not expected to progress" ; + let* _ = Mempool.get_mempool client in + unit + let register ~protocols = check_node_version_check_bypass_test protocols ; check_node_version_allowed_test protocols ; @@ -646,4 +763,5 @@ let register ~protocols = baker_remote_test protocols ; baker_check_consensus_branch protocols ; force_apply_from_round protocols ; - simple_attestations_aggregation protocols + simple_attestations_aggregation protocols ; + prequorum_check_levels protocols -- GitLab From cccbc27f2370b5827d697216d0a91b29fa6fa1fb Mon Sep 17 00:00:00 2001 From: Adam Allombert-Goget Date: Fri, 4 Apr 2025 10:15:06 +0200 Subject: [PATCH 2/4] baker: improve voting power monitoring --- .../lib_delegate/baking_actions.ml | 1 + src/proto_alpha/lib_delegate/baking_lib.ml | 1 + .../lib_delegate/operation_worker.ml | 19 ++++++++++++------- .../lib_delegate/operation_worker.mli | 1 + 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/proto_alpha/lib_delegate/baking_actions.ml b/src/proto_alpha/lib_delegate/baking_actions.ml index 7e80347a0cc3..59346da12915 100644 --- a/src/proto_alpha/lib_delegate/baking_actions.ml +++ b/src/proto_alpha/lib_delegate/baking_actions.ml @@ -916,6 +916,7 @@ let prepare_waiting_for_quorum state = let candidate = { Operation_worker.hash = latest_proposal.hash; + level_watched = latest_proposal.shell.level; round_watched = latest_proposal.round; payload_hash_watched = latest_proposal.payload_hash; } diff --git a/src/proto_alpha/lib_delegate/baking_lib.ml b/src/proto_alpha/lib_delegate/baking_lib.ml index 4b5117f32e77..8c241ee2186d 100644 --- a/src/proto_alpha/lib_delegate/baking_lib.ml +++ b/src/proto_alpha/lib_delegate/baking_lib.ml @@ -410,6 +410,7 @@ let propose (cctxt : Protocol_client_context.full) ?minimal_fees let candidate = { Operation_worker.hash = latest_proposal.hash; + level_watched = latest_proposal.shell.level; round_watched = latest_proposal.round; payload_hash_watched = latest_proposal.payload_hash; } diff --git a/src/proto_alpha/lib_delegate/operation_worker.ml b/src/proto_alpha/lib_delegate/operation_worker.ml index 924da2ebd83d..ffb9ce8fab17 100644 --- a/src/proto_alpha/lib_delegate/operation_worker.ml +++ b/src/proto_alpha/lib_delegate/operation_worker.ml @@ -175,6 +175,7 @@ end type candidate = { hash : Block_hash.t; + level_watched : Int32.t; round_watched : Round.t; payload_hash_watched : Block_payload_hash.t; } @@ -182,12 +183,13 @@ type candidate = { let candidate_encoding = let open Data_encoding in conv - (fun {hash; round_watched; payload_hash_watched} -> - (hash, round_watched, payload_hash_watched)) - (fun (hash, round_watched, payload_hash_watched) -> - {hash; round_watched; payload_hash_watched}) - (obj3 + (fun {hash; level_watched; round_watched; payload_hash_watched} -> + (hash, level_watched, round_watched, payload_hash_watched)) + (fun (hash, level_watched, round_watched, payload_hash_watched) -> + {hash; level_watched; round_watched; payload_hash_watched}) + (obj4 (req "hash" Block_hash.encoding) + (req "level_watched" int32) (req "round_watched" Round.encoding) (req "payload_hash_watched" Block_payload_hash.encoding)) @@ -339,8 +341,11 @@ let make_initial_state ?(monitor_node_operations = true) ~constants () = } let is_valid_consensus_content (candidate : candidate) consensus_content = - let {hash = _; round_watched; payload_hash_watched} = candidate in - Round.equal consensus_content.round round_watched + let {hash = _; level_watched; round_watched; payload_hash_watched} = + candidate + in + Int32.equal (Raw_level.to_int32 consensus_content.level) level_watched + && Round.equal consensus_content.round round_watched && Block_payload_hash.equal consensus_content.block_payload_hash payload_hash_watched diff --git a/src/proto_alpha/lib_delegate/operation_worker.mli b/src/proto_alpha/lib_delegate/operation_worker.mli index 70be64c236dd..295eafeddc6c 100644 --- a/src/proto_alpha/lib_delegate/operation_worker.mli +++ b/src/proto_alpha/lib_delegate/operation_worker.mli @@ -41,6 +41,7 @@ type t type candidate = { hash : Block_hash.t; + level_watched : Int32.t; round_watched : Round.t; payload_hash_watched : Block_payload_hash.t; } -- GitLab From 0dca870dacf36faa1b1d796ecd8dffcb8bfaf42d Mon Sep 17 00:00:00 2001 From: Adam Allombert-Goget Date: Fri, 4 Apr 2025 12:20:58 +0200 Subject: [PATCH 3/4] 021_PsQuebec/baker: improve voting power monitoring Porting to proto 021_PsQuebec ae574d6d1418e0509a3236119bbc97a1878c08ef - baker: improve voting power monitoring --- .../lib_delegate/baking_actions.ml | 1 + .../lib_delegate/baking_lib.ml | 1 + .../lib_delegate/operation_worker.ml | 19 ++++++++++++------- .../lib_delegate/operation_worker.mli | 1 + 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/proto_021_PsQuebec/lib_delegate/baking_actions.ml b/src/proto_021_PsQuebec/lib_delegate/baking_actions.ml index 941782fbbbac..45e75fd2b517 100644 --- a/src/proto_021_PsQuebec/lib_delegate/baking_actions.ml +++ b/src/proto_021_PsQuebec/lib_delegate/baking_actions.ml @@ -899,6 +899,7 @@ let prepare_waiting_for_quorum state = let candidate = { Operation_worker.hash = latest_proposal.hash; + level_watched = latest_proposal.shell.level; round_watched = latest_proposal.round; payload_hash_watched = latest_proposal.payload_hash; } diff --git a/src/proto_021_PsQuebec/lib_delegate/baking_lib.ml b/src/proto_021_PsQuebec/lib_delegate/baking_lib.ml index aa948e0583c2..278d12eb560a 100644 --- a/src/proto_021_PsQuebec/lib_delegate/baking_lib.ml +++ b/src/proto_021_PsQuebec/lib_delegate/baking_lib.ml @@ -416,6 +416,7 @@ let propose (cctxt : Protocol_client_context.full) ?minimal_fees let candidate = { Operation_worker.hash = latest_proposal.hash; + level_watched = latest_proposal.shell.level; round_watched = latest_proposal.round; payload_hash_watched = latest_proposal.payload_hash; } diff --git a/src/proto_021_PsQuebec/lib_delegate/operation_worker.ml b/src/proto_021_PsQuebec/lib_delegate/operation_worker.ml index 2d2b9c54fcea..fe816a860ef6 100644 --- a/src/proto_021_PsQuebec/lib_delegate/operation_worker.ml +++ b/src/proto_021_PsQuebec/lib_delegate/operation_worker.ml @@ -175,6 +175,7 @@ end type candidate = { hash : Block_hash.t; + level_watched : Int32.t; round_watched : Round.t; payload_hash_watched : Block_payload_hash.t; } @@ -182,12 +183,13 @@ type candidate = { let candidate_encoding = let open Data_encoding in conv - (fun {hash; round_watched; payload_hash_watched} -> - (hash, round_watched, payload_hash_watched)) - (fun (hash, round_watched, payload_hash_watched) -> - {hash; round_watched; payload_hash_watched}) - (obj3 + (fun {hash; level_watched; round_watched; payload_hash_watched} -> + (hash, level_watched, round_watched, payload_hash_watched)) + (fun (hash, level_watched, round_watched, payload_hash_watched) -> + {hash; level_watched; round_watched; payload_hash_watched}) + (obj4 (req "hash" Block_hash.encoding) + (req "level_watched" int32) (req "round_watched" Round.encoding) (req "payload_hash_watched" Block_payload_hash.encoding)) @@ -339,8 +341,11 @@ let make_initial_state ?(monitor_node_operations = true) ~constants () = } let is_valid_consensus_content (candidate : candidate) consensus_content = - let {hash = _; round_watched; payload_hash_watched} = candidate in - Round.equal consensus_content.round round_watched + let {hash = _; level_watched; round_watched; payload_hash_watched} = + candidate + in + Int32.equal (Raw_level.to_int32 consensus_content.level) level_watched + && Round.equal consensus_content.round round_watched && Block_payload_hash.equal consensus_content.block_payload_hash payload_hash_watched diff --git a/src/proto_021_PsQuebec/lib_delegate/operation_worker.mli b/src/proto_021_PsQuebec/lib_delegate/operation_worker.mli index 2ddcfca5c4b2..8b799ed2a2a3 100644 --- a/src/proto_021_PsQuebec/lib_delegate/operation_worker.mli +++ b/src/proto_021_PsQuebec/lib_delegate/operation_worker.mli @@ -35,6 +35,7 @@ type t type candidate = { hash : Block_hash.t; + level_watched : Int32.t; round_watched : Round.t; payload_hash_watched : Block_payload_hash.t; } -- GitLab From 0c4d81b73dd33be04111e9c20908c338226ba956 Mon Sep 17 00:00:00 2001 From: Adam Allombert-Goget Date: Fri, 4 Apr 2025 12:20:58 +0200 Subject: [PATCH 4/4] 022_PsRiotum/baker: improve voting power monitoring Porting to proto 022_PsRiotum ae574d6d1418e0509a3236119bbc97a1878c08ef - baker: improve voting power monitoring --- .../lib_delegate/baking_actions.ml | 1 + .../lib_delegate/baking_lib.ml | 1 + .../lib_delegate/operation_worker.ml | 19 ++++++++++++------- .../lib_delegate/operation_worker.mli | 1 + 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/proto_022_PsRiotum/lib_delegate/baking_actions.ml b/src/proto_022_PsRiotum/lib_delegate/baking_actions.ml index c5e673e30cbc..3b1e42ba4313 100644 --- a/src/proto_022_PsRiotum/lib_delegate/baking_actions.ml +++ b/src/proto_022_PsRiotum/lib_delegate/baking_actions.ml @@ -898,6 +898,7 @@ let prepare_waiting_for_quorum state = let candidate = { Operation_worker.hash = latest_proposal.hash; + level_watched = latest_proposal.shell.level; round_watched = latest_proposal.round; payload_hash_watched = latest_proposal.payload_hash; } diff --git a/src/proto_022_PsRiotum/lib_delegate/baking_lib.ml b/src/proto_022_PsRiotum/lib_delegate/baking_lib.ml index 4b5117f32e77..8c241ee2186d 100644 --- a/src/proto_022_PsRiotum/lib_delegate/baking_lib.ml +++ b/src/proto_022_PsRiotum/lib_delegate/baking_lib.ml @@ -410,6 +410,7 @@ let propose (cctxt : Protocol_client_context.full) ?minimal_fees let candidate = { Operation_worker.hash = latest_proposal.hash; + level_watched = latest_proposal.shell.level; round_watched = latest_proposal.round; payload_hash_watched = latest_proposal.payload_hash; } diff --git a/src/proto_022_PsRiotum/lib_delegate/operation_worker.ml b/src/proto_022_PsRiotum/lib_delegate/operation_worker.ml index 924da2ebd83d..ffb9ce8fab17 100644 --- a/src/proto_022_PsRiotum/lib_delegate/operation_worker.ml +++ b/src/proto_022_PsRiotum/lib_delegate/operation_worker.ml @@ -175,6 +175,7 @@ end type candidate = { hash : Block_hash.t; + level_watched : Int32.t; round_watched : Round.t; payload_hash_watched : Block_payload_hash.t; } @@ -182,12 +183,13 @@ type candidate = { let candidate_encoding = let open Data_encoding in conv - (fun {hash; round_watched; payload_hash_watched} -> - (hash, round_watched, payload_hash_watched)) - (fun (hash, round_watched, payload_hash_watched) -> - {hash; round_watched; payload_hash_watched}) - (obj3 + (fun {hash; level_watched; round_watched; payload_hash_watched} -> + (hash, level_watched, round_watched, payload_hash_watched)) + (fun (hash, level_watched, round_watched, payload_hash_watched) -> + {hash; level_watched; round_watched; payload_hash_watched}) + (obj4 (req "hash" Block_hash.encoding) + (req "level_watched" int32) (req "round_watched" Round.encoding) (req "payload_hash_watched" Block_payload_hash.encoding)) @@ -339,8 +341,11 @@ let make_initial_state ?(monitor_node_operations = true) ~constants () = } let is_valid_consensus_content (candidate : candidate) consensus_content = - let {hash = _; round_watched; payload_hash_watched} = candidate in - Round.equal consensus_content.round round_watched + let {hash = _; level_watched; round_watched; payload_hash_watched} = + candidate + in + Int32.equal (Raw_level.to_int32 consensus_content.level) level_watched + && Round.equal consensus_content.round round_watched && Block_payload_hash.equal consensus_content.block_payload_hash payload_hash_watched diff --git a/src/proto_022_PsRiotum/lib_delegate/operation_worker.mli b/src/proto_022_PsRiotum/lib_delegate/operation_worker.mli index 70be64c236dd..295eafeddc6c 100644 --- a/src/proto_022_PsRiotum/lib_delegate/operation_worker.mli +++ b/src/proto_022_PsRiotum/lib_delegate/operation_worker.mli @@ -41,6 +41,7 @@ type t type candidate = { hash : Block_hash.t; + level_watched : Int32.t; round_watched : Round.t; payload_hash_watched : Block_payload_hash.t; } -- GitLab