mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-08 01:05:47 +00:00
Fix fork transition case
This commit is contained in:
@@ -757,40 +757,31 @@ mod tests {
|
|||||||
// First Gloas block (V29 node).
|
// First Gloas block (V29 node).
|
||||||
let gloas_slot = if skip_first_gloas_slot { 33 } else { 32 };
|
let gloas_slot = if skip_first_gloas_slot { 33 } else { 32 };
|
||||||
|
|
||||||
// For Full: execution_payload_parent_hash must match the V17 parent's EL hash.
|
// The first Gloas block should always have the pre-Gloas block as its execution parent,
|
||||||
// The V17 parent's EL hash = ExecutionBlockHash::from_root(get_root(1)) = get_hash(1).
|
// although this is currently not checked anywhere (the spec doesn't mention this).
|
||||||
// For Empty: use a non-matching hash.
|
|
||||||
let parent_hash = if first_gloas_block_full {
|
|
||||||
get_hash(1)
|
|
||||||
} else {
|
|
||||||
get_hash(99)
|
|
||||||
};
|
|
||||||
|
|
||||||
ops.push(Operation::ProcessBlock {
|
ops.push(Operation::ProcessBlock {
|
||||||
slot: Slot::new(gloas_slot),
|
slot: Slot::new(gloas_slot),
|
||||||
root: get_root(2),
|
root: get_root(2),
|
||||||
parent_root: get_root(1),
|
parent_root: get_root(1),
|
||||||
justified_checkpoint: get_checkpoint(0),
|
justified_checkpoint: get_checkpoint(0),
|
||||||
finalized_checkpoint: get_checkpoint(0),
|
finalized_checkpoint: get_checkpoint(0),
|
||||||
execution_payload_parent_hash: Some(parent_hash),
|
execution_payload_parent_hash: Some(get_hash(1)),
|
||||||
execution_payload_block_hash: Some(get_hash(2)),
|
execution_payload_block_hash: Some(get_hash(2)),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify the parent_payload_status is correctly set.
|
// Parent payload status of fork boundary block should always be Empty.
|
||||||
let expected_parent_status = if first_gloas_block_full {
|
let expected_parent_status = PayloadStatus::Empty;
|
||||||
PayloadStatus::Full
|
|
||||||
} else {
|
|
||||||
PayloadStatus::Empty
|
|
||||||
};
|
|
||||||
ops.push(Operation::AssertParentPayloadStatus {
|
ops.push(Operation::AssertParentPayloadStatus {
|
||||||
block_root: get_root(2),
|
block_root: get_root(2),
|
||||||
expected_status: expected_parent_status,
|
expected_status: expected_parent_status,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mark root 2's execution payload as received so the Full virtual child exists.
|
// Mark root 2's execution payload as received so the Full virtual child exists.
|
||||||
|
if first_gloas_block_full {
|
||||||
ops.push(Operation::ProcessExecutionPayload {
|
ops.push(Operation::ProcessExecutionPayload {
|
||||||
block_root: get_root(2),
|
block_root: get_root(2),
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Extend the chain with another V29 block (Full child of root 2).
|
// Extend the chain with another V29 block (Full child of root 2).
|
||||||
ops.push(Operation::ProcessBlock {
|
ops.push(Operation::ProcessBlock {
|
||||||
@@ -799,7 +790,11 @@ mod tests {
|
|||||||
parent_root: get_root(2),
|
parent_root: get_root(2),
|
||||||
justified_checkpoint: get_checkpoint(0),
|
justified_checkpoint: get_checkpoint(0),
|
||||||
finalized_checkpoint: get_checkpoint(0),
|
finalized_checkpoint: get_checkpoint(0),
|
||||||
execution_payload_parent_hash: Some(get_hash(2)),
|
execution_payload_parent_hash: if first_gloas_block_full {
|
||||||
|
Some(get_hash(2))
|
||||||
|
} else {
|
||||||
|
Some(get_hash(1))
|
||||||
|
},
|
||||||
execution_payload_block_hash: Some(get_hash(3)),
|
execution_payload_block_hash: Some(get_hash(3)),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -813,6 +808,15 @@ mod tests {
|
|||||||
expected_payload_status: None,
|
expected_payload_status: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ops.push(Operation::AssertParentPayloadStatus {
|
||||||
|
block_root: get_root(3),
|
||||||
|
expected_status: if first_gloas_block_full {
|
||||||
|
PayloadStatus::Full
|
||||||
|
} else {
|
||||||
|
PayloadStatus::Empty
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
ForkChoiceTestDefinition {
|
ForkChoiceTestDefinition {
|
||||||
finalized_block_slot: Slot::new(0),
|
finalized_block_slot: Slot::new(0),
|
||||||
justified_checkpoint: get_checkpoint(0),
|
justified_checkpoint: get_checkpoint(0),
|
||||||
|
|||||||
@@ -570,29 +570,29 @@ impl ProtoArray {
|
|||||||
block_root: block.root,
|
block_root: block.root,
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let parent_payload_status: PayloadStatus = if let Some(parent_node) =
|
let parent_payload_status: PayloadStatus =
|
||||||
parent_index.and_then(|idx| self.nodes.get(idx))
|
if let Some(parent_node) = parent_index.and_then(|idx| self.nodes.get(idx)) {
|
||||||
{
|
match parent_node {
|
||||||
// Get the parent's execution block hash, handling both V17 and V29 nodes.
|
ProtoNode::V29(v29) => {
|
||||||
// V17 parents occur during the Gloas fork transition.
|
// Both parent and child are Gloas blocks. The parent is full if the
|
||||||
// TODO(gloas): the spec's `get_parent_payload_status` assumes all blocks are
|
// block hash in the parent node matches the parent block hash in the
|
||||||
// post-Gloas with bids. Revisit once the spec clarifies fork-transition behavior.
|
// child bid.
|
||||||
let parent_el_block_hash = match parent_node {
|
if execution_payload_parent_hash == v29.execution_payload_block_hash {
|
||||||
ProtoNode::V29(v29) => Some(v29.execution_payload_block_hash),
|
|
||||||
ProtoNode::V17(v17) => v17.execution_status.block_hash(),
|
|
||||||
};
|
|
||||||
// Per spec's `is_parent_node_full`: if the child's EL parent hash
|
|
||||||
// matches the parent's EL block hash, the child extends the parent's
|
|
||||||
// payload chain, meaning the parent was Full.
|
|
||||||
if parent_el_block_hash.is_some_and(|hash| execution_payload_parent_hash == hash) {
|
|
||||||
PayloadStatus::Full
|
PayloadStatus::Full
|
||||||
} else {
|
} else {
|
||||||
PayloadStatus::Empty
|
PayloadStatus::Empty
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
ProtoNode::V17(_) => {
|
||||||
|
// Parent is pre-Gloas, pre-Gloas blocks are treated as having Empty
|
||||||
|
// payload status. This case is reached during the fork transition.
|
||||||
|
PayloadStatus::Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// TODO(gloas): re-assess this assumption
|
||||||
// Parent is missing (genesis or pruned due to finalization). Default to Full
|
// Parent is missing (genesis or pruned due to finalization). Default to Full
|
||||||
// since this path should only be hit at Gloas genesis, and extending the payload
|
// since this path should only be hit at Gloas genesis.
|
||||||
// chain is the safe default.
|
|
||||||
PayloadStatus::Full
|
PayloadStatus::Full
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user