mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-20 22:38:34 +00:00
Re-do head_payload_status
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user