Fix fork choice compliance tests

This commit is contained in:
dapplion
2026-06-08 21:48:20 +02:00
parent c1b60f1c80
commit d3416ccc8a
5 changed files with 45 additions and 5 deletions

View File

@@ -1303,7 +1303,7 @@ impl ProtoArray {
/// This is similar to `find_head_walk`, except it walks every viable branch instead of taking /// This is similar to `find_head_walk`, except it walks every viable branch instead of taking
/// the maximum child at each step. /// the maximum child at each step.
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn filtered_block_tree_leaves_and_weights<E: EthSpec>( pub(crate) fn filtered_block_tree_leaves_and_weights<E: EthSpec>(
&self, &self,
justified_root: &Hash256, justified_root: &Hash256,
current_slot: Slot, current_slot: Slot,

View File

@@ -1119,6 +1119,33 @@ impl ProtoArrayForkChoice {
.map(|node| node.weight()) .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<E: EthSpec>(
&self,
justified_root: &Hash256,
current_slot: Slot,
justified_checkpoint: Checkpoint,
finalized_checkpoint: Checkpoint,
proposer_boost_root: Hash256,
justified_balances: &JustifiedBalances,
spec: &ChainSpec,
) -> Result<Vec<(Hash256, PayloadStatus, u64)>, String> {
self.proto_array
.filtered_block_tree_leaves_and_weights::<E>(
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. /// Returns the payload status of the head node based on accumulated weights and tiebreaker.
/// ///
/// See `ProtoArray` documentation. /// See `ProtoArray` documentation.

View File

@@ -87,7 +87,9 @@ excluded_paths = [
# TODO: fast confirmation rule not merged yet # TODO: fast confirmation rule not merged yet
"tests/.*/.*/fast_confirmation", "tests/.*/.*/fast_confirmation",
# TODO: fork choice compliance invalid_message tests not implemented yet # 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/.*",
] ]

View File

@@ -660,6 +660,16 @@ impl<E: EthSpec> Tester<E> {
Ok(self.harness.chain.canonical_head.cached_head()) 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) { pub fn set_tick(&self, tick: u64) {
self.harness self.harness
.chain .chain
@@ -719,6 +729,7 @@ impl<E: EthSpec> Tester<E> {
}; };
let block = Arc::new(block); let block = Arc::new(block);
self.refresh_head_for_current_slot_block(block.slot())?;
let result: Result<Result<Hash256, ()>, _> = self let result: Result<Result<Hash256, ()>, _> = self
.block_on_dangerous(self.harness.chain.process_block( .block_on_dangerous(self.harness.chain.process_block(
block_root, block_root,
@@ -828,6 +839,7 @@ impl<E: EthSpec> Tester<E> {
}; };
let block = Arc::new(block); let block = Arc::new(block);
self.refresh_head_for_current_slot_block(block.slot())?;
let result: Result<Result<Hash256, ()>, _> = self let result: Result<Result<Hash256, ()>, _> = self
.block_on_dangerous(self.harness.chain.process_block( .block_on_dangerous(self.harness.chain.process_block(
block_root, block_root,
@@ -1412,7 +1424,6 @@ impl<E: EthSpec> Tester<E> {
let justified_balances = fork_choice.fc_store().justified_balances().clone(); let justified_balances = fork_choice.fc_store().justified_balances().clone();
let actual = fork_choice let actual = fork_choice
.proto_array() .proto_array()
.core_proto_array()
.filtered_block_tree_leaves_and_weights::<E>( .filtered_block_tree_leaves_and_weights::<E>(
&justified.root, &justified.root,
current_slot, current_slot,
@@ -1424,7 +1435,7 @@ impl<E: EthSpec> Tester<E> {
) )
.map_err(|e| { .map_err(|e| {
Error::InternalError(format!( Error::InternalError(format!(
"filtered_block_tree_leaves_and_weights failed: {e:?}" "filtered_block_tree_leaves_and_weights failed: {e}"
)) ))
})?; })?;
drop(fork_choice); drop(fork_choice);

View File

@@ -779,7 +779,7 @@ impl<E: EthSpec + TypeName> Handler for ForkChoiceComplianceHandler<E> {
} }
fn is_enabled_for_fork(&self, fork_name: ForkName) -> bool { 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<ForkName> { fn disabled_forks(&self) -> Vec<ForkName> {