From d3416ccc8a70515d5f7c08419a09430709aac964 Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Mon, 8 Jun 2026 21:48:20 +0200 Subject: [PATCH] Fix fork choice compliance tests --- consensus/proto_array/src/proto_array.rs | 2 +- .../src/proto_array_fork_choice.rs | 27 +++++++++++++++++++ testing/ef_tests/check_all_files_accessed.py | 4 ++- testing/ef_tests/src/cases/fork_choice.rs | 15 +++++++++-- testing/ef_tests/src/handler.rs | 2 +- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/consensus/proto_array/src/proto_array.rs b/consensus/proto_array/src/proto_array.rs index a669323afa..bea561c8ef 100644 --- a/consensus/proto_array/src/proto_array.rs +++ b/consensus/proto_array/src/proto_array.rs @@ -1303,7 +1303,7 @@ impl ProtoArray { /// This is similar to `find_head_walk`, except it walks every viable branch instead of taking /// the maximum child at each step. #[allow(clippy::too_many_arguments)] - pub fn filtered_block_tree_leaves_and_weights( + pub(crate) fn filtered_block_tree_leaves_and_weights( &self, justified_root: &Hash256, current_slot: Slot, diff --git a/consensus/proto_array/src/proto_array_fork_choice.rs b/consensus/proto_array/src/proto_array_fork_choice.rs index 9711f56b0b..c75a5d023f 100644 --- a/consensus/proto_array/src/proto_array_fork_choice.rs +++ b/consensus/proto_array/src/proto_array_fork_choice.rs @@ -1119,6 +1119,33 @@ impl ProtoArrayForkChoice { .map(|node| node.weight()) } + /// Returns the leaves of the filtered block tree (rooted at `justified_root`) along with + /// their weights — i.e. roots that are viable for head and have no descendant that is also + /// viable for head. Mirrors the spec's `viable_for_head_roots_and_weights` check. + #[allow(clippy::too_many_arguments)] + pub fn filtered_block_tree_leaves_and_weights( + &self, + justified_root: &Hash256, + current_slot: Slot, + justified_checkpoint: Checkpoint, + finalized_checkpoint: Checkpoint, + proposer_boost_root: Hash256, + justified_balances: &JustifiedBalances, + spec: &ChainSpec, + ) -> Result, String> { + self.proto_array + .filtered_block_tree_leaves_and_weights::( + justified_root, + current_slot, + justified_checkpoint, + finalized_checkpoint, + proposer_boost_root, + justified_balances, + spec, + ) + .map_err(|e| format!("filtered_block_tree_leaves_and_weights failed: {e:?}")) + } + /// Returns the payload status of the head node based on accumulated weights and tiebreaker. /// /// See `ProtoArray` documentation. diff --git a/testing/ef_tests/check_all_files_accessed.py b/testing/ef_tests/check_all_files_accessed.py index 28a84f04fb..85e35b5147 100755 --- a/testing/ef_tests/check_all_files_accessed.py +++ b/testing/ef_tests/check_all_files_accessed.py @@ -87,7 +87,9 @@ excluded_paths = [ # TODO: fast confirmation rule not merged yet "tests/.*/.*/fast_confirmation", # TODO: fork choice compliance invalid_message tests not implemented yet - "tests/minimal/.*/fork_choice_compliance/invalid_message_test/.*" + "tests/minimal/.*/fork_choice_compliance/invalid_message_test/.*", + # TODO: fork choice compliance tests are implemented for Fulu only. + "tests/minimal/gloas/fork_choice_compliance/.*", ] diff --git a/testing/ef_tests/src/cases/fork_choice.rs b/testing/ef_tests/src/cases/fork_choice.rs index fd65ae290a..4c901838a9 100644 --- a/testing/ef_tests/src/cases/fork_choice.rs +++ b/testing/ef_tests/src/cases/fork_choice.rs @@ -660,6 +660,16 @@ impl Tester { Ok(self.harness.chain.canonical_head.cached_head()) } + fn refresh_head_for_current_slot_block(&self, block_slot: Slot) -> Result<(), Error> { + let current_slot = self.harness.chain.slot().map_err(|e| { + Error::InternalError(format!("reading current slot failed with {:?}", e)) + })?; + if block_slot == current_slot { + self.find_head()?; + } + Ok(()) + } + pub fn set_tick(&self, tick: u64) { self.harness .chain @@ -719,6 +729,7 @@ impl Tester { }; let block = Arc::new(block); + self.refresh_head_for_current_slot_block(block.slot())?; let result: Result, _> = self .block_on_dangerous(self.harness.chain.process_block( block_root, @@ -828,6 +839,7 @@ impl Tester { }; let block = Arc::new(block); + self.refresh_head_for_current_slot_block(block.slot())?; let result: Result, _> = self .block_on_dangerous(self.harness.chain.process_block( block_root, @@ -1412,7 +1424,6 @@ impl Tester { let justified_balances = fork_choice.fc_store().justified_balances().clone(); let actual = fork_choice .proto_array() - .core_proto_array() .filtered_block_tree_leaves_and_weights::( &justified.root, current_slot, @@ -1424,7 +1435,7 @@ impl Tester { ) .map_err(|e| { Error::InternalError(format!( - "filtered_block_tree_leaves_and_weights failed: {e:?}" + "filtered_block_tree_leaves_and_weights failed: {e}" )) })?; drop(fork_choice); diff --git a/testing/ef_tests/src/handler.rs b/testing/ef_tests/src/handler.rs index 64ca54069c..1a4db0d3bd 100644 --- a/testing/ef_tests/src/handler.rs +++ b/testing/ef_tests/src/handler.rs @@ -779,7 +779,7 @@ impl Handler for ForkChoiceComplianceHandler { } fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool { - cfg!(feature = "fake_crypto") && fork_name.fulu_enabled() + cfg!(feature = "fake_crypto") && fork_name == ForkName::Fulu } fn disabled_forks(&self) -> Vec {