Re-do head_payload_status

This commit is contained in:
Michael Sproul
2026-03-25 14:05:11 +11:00
parent c841603003
commit 8b448864f0
18 changed files with 143 additions and 119 deletions

View File

@@ -29,6 +29,8 @@ pub enum Operation {
justified_state_balances: Vec<u64>,
expected_head: Hash256,
current_slot: Slot,
#[serde(default)]
expected_payload_status: Option<PayloadStatus>,
},
ProposerBoostFindHead {
justified_checkpoint: Checkpoint,
@@ -88,11 +90,6 @@ pub enum Operation {
block_root: Hash256,
expected_status: PayloadStatus,
},
AssertHeadPayloadStatus {
head_root: Hash256,
expected_status: PayloadStatus,
current_slot: Slot,
},
SetPayloadTiebreak {
block_root: Hash256,
is_timely: bool,
@@ -159,11 +156,12 @@ impl ForkChoiceTestDefinition {
justified_state_balances,
expected_head,
current_slot,
expected_payload_status,
} => {
let justified_balances =
JustifiedBalances::from_effective_balances(justified_state_balances)
.unwrap();
let head = fork_choice
let (head, payload_status) = fork_choice
.find_head::<MainnetEthSpec>(
justified_checkpoint,
finalized_checkpoint,
@@ -182,6 +180,13 @@ impl ForkChoiceTestDefinition {
"Operation at index {} failed head check. Operation: {:?}",
op_index, op
);
if let Some(expected_status) = expected_payload_status {
assert_eq!(
payload_status, expected_status,
"Operation at index {} failed payload status check. Operation: {:?}",
op_index, op
);
}
check_bytes_round_trip(&fork_choice);
}
Operation::ProposerBoostFindHead {
@@ -194,7 +199,7 @@ impl ForkChoiceTestDefinition {
let justified_balances =
JustifiedBalances::from_effective_balances(justified_state_balances)
.unwrap();
let head = fork_choice
let (head, _payload_status) = fork_choice
.find_head::<MainnetEthSpec>(
justified_checkpoint,
finalized_checkpoint,
@@ -455,25 +460,6 @@ impl ForkChoiceTestDefinition {
op_index
);
}
Operation::AssertHeadPayloadStatus {
head_root,
expected_status,
current_slot,
} => {
let actual = fork_choice
.head_payload_status::<MainnetEthSpec>(&head_root, current_slot)
.unwrap_or_else(|| {
panic!(
"AssertHeadPayloadStatus: head root not found at op index {}",
op_index
)
});
assert_eq!(
actual, expected_status,
"head_payload_status mismatch at op index {}",
op_index
);
}
Operation::SetPayloadTiebreak {
block_root,
is_timely,

View File

@@ -17,6 +17,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(0),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a block with a hash of 2.
@@ -57,6 +58,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a block with a hash of 1 that comes off the genesis block (this is a fork compared
@@ -98,6 +100,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a vote to block 1
@@ -128,6 +131,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(1),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -171,6 +175,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -228,6 +233,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -279,6 +285,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -329,6 +336,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Invalidation of 3 should have removed upstream weight.
@@ -383,6 +391,7 @@ pub fn get_execution_status_test_definition_01() -> ForkChoiceTestDefinition {
justified_state_balances: balances,
expected_head: get_root(1),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -437,6 +446,7 @@ pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(0),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a block with a hash of 2.
@@ -477,6 +487,7 @@ pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a block with a hash of 1 that comes off the genesis block (this is a fork compared
@@ -518,6 +529,7 @@ pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a vote to block 1
@@ -548,6 +560,7 @@ pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(1),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -591,6 +604,7 @@ pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -648,6 +662,7 @@ pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -712,6 +727,7 @@ pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -762,6 +778,7 @@ pub fn get_execution_status_test_definition_02() -> ForkChoiceTestDefinition {
justified_state_balances: balances,
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Invalidation of 3 should have removed upstream weight.
@@ -818,6 +835,7 @@ pub fn get_execution_status_test_definition_03() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(0),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a block with a hash of 2.
@@ -858,6 +876,7 @@ pub fn get_execution_status_test_definition_03() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a block with a hash of 1 that comes off the genesis block (this is a fork compared
@@ -899,6 +918,7 @@ pub fn get_execution_status_test_definition_03() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a vote to block 1
@@ -929,6 +949,7 @@ pub fn get_execution_status_test_definition_03() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(1),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {
@@ -972,6 +993,7 @@ pub fn get_execution_status_test_definition_03() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(1),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::AssertWeight {

View File

@@ -11,6 +11,7 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(0),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Build the following tree (stick? lol).
@@ -65,6 +66,7 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Ensure that with justified epoch 1 we find 3
@@ -86,6 +88,7 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Ensure that with justified epoch 2 we find 3
@@ -103,6 +106,7 @@ pub fn get_ffg_case_01_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances,
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// END OF TESTS
@@ -128,6 +132,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(0),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Build the following tree.
@@ -275,6 +280,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Same as above, but with justified epoch 2.
ops.push(Operation::FindHead {
@@ -286,6 +292,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Same as above, but with justified epoch 3.
//
@@ -301,6 +308,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a vote to 1.
@@ -341,6 +349,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Save as above but justified epoch 2.
ops.push(Operation::FindHead {
@@ -352,6 +361,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Save as above but justified epoch 3.
//
@@ -367,6 +377,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a vote to 2.
@@ -407,6 +418,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Same as above but justified epoch 2.
ops.push(Operation::FindHead {
@@ -418,6 +430,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Same as above but justified epoch 3.
//
@@ -433,6 +446,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Ensure that if we start at 1 we find 9 (just: 0, fin: 0).
@@ -457,6 +471,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Same as above but justified epoch 2.
ops.push(Operation::FindHead {
@@ -468,6 +483,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Same as above but justified epoch 3.
//
@@ -483,6 +499,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Ensure that if we start at 2 we find 10 (just: 0, fin: 0).
@@ -504,6 +521,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Same as above but justified epoch 2.
ops.push(Operation::FindHead {
@@ -515,6 +533,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Same as above but justified epoch 3.
//
@@ -530,6 +549,7 @@ pub fn get_ffg_case_02_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances,
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// END OF TESTS

View File

@@ -78,6 +78,7 @@ pub fn get_gloas_chain_following_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: vec![1],
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ops.push(Operation::SetPayloadTiebreak {
@@ -91,6 +92,7 @@ pub fn get_gloas_chain_following_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: vec![1],
expected_head: get_root(4),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ForkChoiceTestDefinition {
@@ -139,6 +141,8 @@ pub fn get_gloas_payload_probe_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: vec![1, 1],
expected_head: get_root(1),
current_slot: Slot::new(0),
// With MainnetEthSpec PTC_SIZE=512, 1 bit set out of 256 threshold → not timely → Empty.
expected_payload_status: Some(PayloadStatus::Empty),
});
// PTC votes write to bitfields only, not to full/empty weight.
// Weight is 0 because no CL attestations target this block.
@@ -147,12 +151,6 @@ pub fn get_gloas_payload_probe_test_definition() -> ForkChoiceTestDefinition {
expected_full_weight: 0,
expected_empty_weight: 0,
});
// With MainnetEthSpec PTC_SIZE=512, 1 bit set out of 256 threshold → not timely → Empty.
ops.push(Operation::AssertHeadPayloadStatus {
head_root: get_root(1),
expected_status: PayloadStatus::Empty,
current_slot: Slot::new(0),
});
// Flip validator 0 to Empty; both bits now clear.
ops.push(Operation::ProcessPayloadAttestation {
@@ -168,17 +166,13 @@ pub fn get_gloas_payload_probe_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: vec![1, 1],
expected_head: get_root(1),
current_slot: Slot::new(0),
expected_payload_status: Some(PayloadStatus::Empty),
});
ops.push(Operation::AssertPayloadWeights {
block_root: get_root(1),
expected_full_weight: 0,
expected_empty_weight: 0,
});
ops.push(Operation::AssertHeadPayloadStatus {
head_root: get_root(1),
expected_status: PayloadStatus::Empty,
current_slot: Slot::new(0),
});
// Same-slot attestation to a new head candidate should be Pending (no payload bucket change).
// Root 5 is an Empty child of root_1 (parent_hash doesn't match root_1's block_hash),
@@ -205,17 +199,13 @@ pub fn get_gloas_payload_probe_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: vec![1, 1, 1],
expected_head: get_root(5),
current_slot: Slot::new(0),
expected_payload_status: Some(PayloadStatus::Empty),
});
ops.push(Operation::AssertPayloadWeights {
block_root: get_root(5),
expected_full_weight: 0,
expected_empty_weight: 0,
});
ops.push(Operation::AssertHeadPayloadStatus {
head_root: get_root(5),
expected_status: PayloadStatus::Empty,
current_slot: Slot::new(0),
});
ForkChoiceTestDefinition {
finalized_block_slot: Slot::new(0),
@@ -289,6 +279,7 @@ pub fn get_gloas_find_head_vote_transition_test_definition() -> ForkChoiceTestDe
justified_state_balances: vec![1],
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// CL attestation to Empty branch (root 4) from validator 0 → head flips to 4.
@@ -303,6 +294,7 @@ pub fn get_gloas_find_head_vote_transition_test_definition() -> ForkChoiceTestDe
justified_state_balances: vec![1],
expected_head: get_root(4),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// CL attestation back to Full branch (root 3) → head returns to 3.
@@ -317,6 +309,7 @@ pub fn get_gloas_find_head_vote_transition_test_definition() -> ForkChoiceTestDe
justified_state_balances: vec![1],
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ForkChoiceTestDefinition {
@@ -391,6 +384,7 @@ pub fn get_gloas_weight_priority_over_payload_preference_test_definition()
justified_state_balances: vec![1],
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Two CL attestations to the Empty branch make it strictly heavier,
@@ -411,6 +405,7 @@ pub fn get_gloas_weight_priority_over_payload_preference_test_definition()
justified_state_balances: vec![1, 1],
expected_head: get_root(4),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ForkChoiceTestDefinition {
@@ -559,6 +554,7 @@ pub fn get_gloas_interleaved_attestations_test_definition() -> ForkChoiceTestDef
justified_state_balances: vec![1, 1],
expected_head: get_root(4),
current_slot: Slot::new(1),
expected_payload_status: None,
});
// Step 5: Flip tiebreaker to Full → Full branch wins.
@@ -573,6 +569,7 @@ pub fn get_gloas_interleaved_attestations_test_definition() -> ForkChoiceTestDef
justified_state_balances: vec![1, 1],
expected_head: get_root(3),
current_slot: Slot::new(100),
expected_payload_status: None,
});
// Step 6: Add extra CL weight to Empty branch → overrides Full tiebreaker.
@@ -587,6 +584,7 @@ pub fn get_gloas_interleaved_attestations_test_definition() -> ForkChoiceTestDef
justified_state_balances: vec![1, 1, 1],
expected_head: get_root(4),
current_slot: Slot::new(100),
expected_payload_status: None,
});
ForkChoiceTestDefinition {
@@ -673,6 +671,7 @@ pub fn get_gloas_payload_received_interleaving_test_definition() -> ForkChoiceTe
justified_state_balances: vec![1, 1],
expected_head: get_root(1),
current_slot: Slot::new(100),
expected_payload_status: None,
});
// ProcessExecutionPayload on genesis is a no-op (already received at init).
@@ -701,6 +700,7 @@ pub fn get_gloas_payload_received_interleaving_test_definition() -> ForkChoiceTe
justified_state_balances: vec![1, 1],
expected_head: get_root(1),
current_slot: Slot::new(100),
expected_payload_status: None,
});
ForkChoiceTestDefinition {

View File

@@ -19,6 +19,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: Hash256::zero(),
current_slot: Slot::new(0),
expected_payload_status: None,
},
// Add block 2
//
@@ -57,6 +58,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
},
// Add block 1
//
@@ -95,6 +97,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
},
// Add block 3
//
@@ -137,6 +140,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
},
// Add block 4
//
@@ -179,6 +183,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(4),
current_slot: Slot::new(0),
expected_payload_status: None,
},
// Add block 5 with a justified epoch of 2
//
@@ -222,6 +227,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(5),
current_slot: Slot::new(0),
expected_payload_status: None,
},
// Ensure there is no error when starting from a block that has the
// wrong justified epoch.
@@ -249,6 +255,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(5),
current_slot: Slot::new(0),
expected_payload_status: None,
},
// Set the justified epoch to 2 and the start block to 5 and ensure 5 is the head.
//
@@ -268,6 +275,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(5),
current_slot: Slot::new(0),
expected_payload_status: None,
},
// Add block 6
//
@@ -312,6 +320,7 @@ pub fn get_no_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances,
expected_head: get_root(6),
current_slot: Slot::new(0),
expected_payload_status: None,
},
];

View File

@@ -17,6 +17,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(0),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a block with a hash of 2.
@@ -57,6 +58,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a block with a hash of 1 that comes off the genesis block (this is a fork compared
@@ -98,6 +100,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a vote to block 1
@@ -128,6 +131,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(1),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add a vote to block 2
@@ -158,6 +162,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add block 3.
@@ -202,6 +207,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Move validator #0 vote from 1 to 3
@@ -236,6 +242,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(2),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Move validator #1 vote from 2 to 1 (this is an equivocation, but fork choice doesn't
@@ -271,6 +278,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(3),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add block 4.
@@ -319,6 +327,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(4),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add block 5, which has a justified epoch of 2.
@@ -371,6 +380,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(4),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add block 6, which has a justified epoch of 0.
@@ -516,6 +526,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(6),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Change fork-choice justified epoch to 1, and the start block to 5 and ensure that 9 is
@@ -550,6 +561,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Change fork-choice justified epoch to 1, and the start block to 5 and ensure that 9 is
@@ -629,6 +641,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Introduce 2 more validators into the system
@@ -691,6 +704,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Set the balances of the last two validators to zero
@@ -717,6 +731,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Set the balances of the last two validators back to 1
@@ -743,6 +758,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(10),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Remove the last two validators
@@ -770,6 +786,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Ensure that pruning below the prune threshold does not prune.
@@ -792,6 +809,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Ensure that pruning above the prune threshold does prune.
@@ -831,6 +849,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances.clone(),
expected_head: get_root(9),
current_slot: Slot::new(0),
expected_payload_status: None,
});
// Add block 11
@@ -883,6 +902,7 @@ pub fn get_votes_test_definition() -> ForkChoiceTestDefinition {
justified_state_balances: balances,
expected_head: get_root(11),
current_slot: Slot::new(0),
expected_payload_status: None,
});
ForkChoiceTestDefinition {

View File

@@ -59,7 +59,7 @@ pub enum ExecutionStatus {
}
/// Represents the status of an execution payload post-Gloas.
#[derive(Clone, Copy, Debug, PartialEq, Encode, Decode, Serialize, Deserialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Encode, Decode, Serialize, Deserialize)]
#[ssz(enum_behaviour = "tag")]
#[repr(u8)]
pub enum PayloadStatus {
@@ -616,7 +616,7 @@ impl ProtoArrayForkChoice {
equivocating_indices: &BTreeSet<u64>,
current_slot: Slot,
spec: &ChainSpec,
) -> Result<Hash256, String> {
) -> Result<(Hash256, PayloadStatus), String> {
let old_balances = &mut self.balances;
let new_balances = justified_state_balances;
let node_slots = self
@@ -660,7 +660,6 @@ impl ProtoArrayForkChoice {
new_balances,
spec,
)
.map(|(root, _payload_status)| root)
.map_err(|e| format!("find_head failed: {:?}", e))
}
@@ -1007,49 +1006,6 @@ impl ProtoArrayForkChoice {
/// Returns the payload status of the head node based on accumulated weights and tiebreaker.
///
/// Returns `Full` if `full_payload_weight > empty_payload_weight`.
/// Returns `Empty` if `empty_payload_weight > full_payload_weight`.
/// On ties:
/// - Previous slot (`slot + 1 == current_slot`): prefer Full only when timely and
/// data available (per `should_extend_payload`).
/// - Otherwise: prefer Full when payload has been received.
///
/// Returns `None` for V17 nodes.
// TODO(gloas): delete
pub fn head_payload_status<E: EthSpec>(
&self,
head_root: &Hash256,
current_slot: Slot,
) -> Option<PayloadStatus> {
let node = self.get_proto_node(head_root)?;
let v29 = node.as_v29().ok()?;
// Replicate the spec's virtual tree walk tiebreaker at the head node.
let use_tiebreaker_only = node.slot() + 1 == current_slot;
if !use_tiebreaker_only {
// Compare weights, then fall back to tiebreaker.
if v29.full_payload_weight > v29.empty_payload_weight {
return Some(PayloadStatus::Full);
} else if v29.empty_payload_weight > v29.full_payload_weight {
return Some(PayloadStatus::Empty);
}
// Equal weights: prefer FULL if payload received.
if v29.payload_received {
Some(PayloadStatus::Full)
} else {
Some(PayloadStatus::Empty)
}
} else {
// Previous slot: should_extend_payload tiebreaker.
if node.is_payload_timely::<E>() && node.is_payload_data_available::<E>() {
Some(PayloadStatus::Full)
} else {
Some(PayloadStatus::Empty)
}
}
}
/// See `ProtoArray` documentation.
pub fn is_descendant(&self, ancestor_root: Hash256, descendant_root: Hash256) -> bool {
self.proto_array