addressing comments:

This commit is contained in:
hopinheimer
2026-03-16 19:36:48 -04:00
parent 916d9fb018
commit 9ce88ea3c1
4 changed files with 39 additions and 11 deletions

View File

@@ -54,7 +54,6 @@ pub enum Error {
}, },
InvalidEpochOffset(u64), InvalidEpochOffset(u64),
Arith(ArithError), Arith(ArithError),
GloasNotImplemented,
InvalidNodeVariant { InvalidNodeVariant {
block_root: Hash256, block_root: Hash256,
}, },

View File

@@ -460,10 +460,7 @@ impl ForkChoiceTestDefinition {
current_slot, current_slot,
} => { } => {
let actual = fork_choice let actual = fork_choice
.head_payload_status::<MainnetEthSpec>( .head_payload_status::<MainnetEthSpec>(&head_root, current_slot)
&head_root,
current_slot,
)
.unwrap_or_else(|| { .unwrap_or_else(|| {
panic!( panic!(
"AssertHeadPayloadStatus: head root not found at op index {}", "AssertHeadPayloadStatus: head root not found at op index {}",

View File

@@ -164,6 +164,22 @@ impl Default for ProposerBoost {
} }
} }
/// Accumulated score changes for a single proto-array node during a `find_head` pass.
///
/// `delta` tracks the ordinary LMD-GHOST balance change applied to the concrete block node.
/// This is the same notion of weight that pre-GLOAS fork choice used.
///
/// Under GLOAS we also need to track how votes contribute to the parent's virtual payload
/// branches:
///
/// - `empty_delta` is the balance change attributable to votes that support the `Empty` payload
/// interpretation of the node
/// - `full_delta` is the balance change attributable to votes that support the `Full` payload
/// interpretation of the node
///
/// Votes in `Pending` state only affect `delta`; they do not contribute to either payload bucket.
/// During score application these payload deltas are propagated independently up the tree so that
/// ancestors can compare children using payload-aware tie breaking.
#[derive(Clone, PartialEq, Debug, Copy)] #[derive(Clone, PartialEq, Debug, Copy)]
pub struct NodeDelta { pub struct NodeDelta {
pub delta: i64, pub delta: i64,
@@ -172,8 +188,16 @@ pub struct NodeDelta {
} }
impl NodeDelta { impl NodeDelta {
/// Determine the payload bucket for a vote based on whether the vote's slot matches the /// Classify a vote into the payload bucket it contributes to for `block_slot`.
/// block's slot (Pending), or the vote's `payload_present` flag (Full/Empty). ///
/// Per the GLOAS model:
///
/// - a same-slot vote is `Pending`
/// - a later vote with `payload_present = true` is `Full`
/// - a later vote with `payload_present = false` is `Empty`
///
/// This classification is used only for payload-aware accounting; all votes still contribute to
/// the aggregate `delta`.
pub fn payload_status( pub fn payload_status(
vote_slot: Slot, vote_slot: Slot,
payload_present: bool, payload_present: bool,
@@ -188,7 +212,9 @@ impl NodeDelta {
} }
} }
/// Add a balance to the appropriate payload status. /// Add `balance` to the payload bucket selected by `status`.
///
/// `Pending` votes do not affect payload buckets, so this becomes a no-op for that case.
pub fn add_payload_delta( pub fn add_payload_delta(
&mut self, &mut self,
status: PayloadStatus, status: PayloadStatus,
@@ -206,7 +232,10 @@ impl NodeDelta {
Ok(()) Ok(())
} }
/// Create a delta that only affects the aggregate `delta` field. /// Create a delta that only affects the aggregate block weight.
///
/// This is useful for callers or tests that only care about ordinary LMD-GHOST weight changes
/// and do not need payload-aware accounting.
pub fn from_delta(delta: i64) -> Self { pub fn from_delta(delta: i64) -> Self {
Self { Self {
delta, delta,
@@ -215,7 +244,9 @@ impl NodeDelta {
} }
} }
/// Subtract a balance from the appropriate payload status. /// Subtract `balance` from the payload bucket selected by `status`.
///
/// `Pending` votes do not affect payload buckets, so this becomes a no-op for that case.
pub fn sub_payload_delta( pub fn sub_payload_delta(
&mut self, &mut self,
status: PayloadStatus, status: PayloadStatus,
@@ -1075,7 +1106,7 @@ impl ProtoArray {
boost_node.parent() == Some(parent_index) boost_node.parent() == Some(parent_index)
&& boost_node && boost_node
.parent_payload_status() .parent_payload_status()
.map_or(false, |s| s != PayloadStatus::Full) .is_ok_and(|s| s != PayloadStatus::Full)
}); });
// These three variables are aliases to the three options that we may set the // These three variables are aliases to the three options that we may set the

View File

@@ -999,6 +999,7 @@ impl ProtoArrayForkChoice {
/// - Previous slot (`slot + 1 == current_slot`): prefer Full only when timely and /// - Previous slot (`slot + 1 == current_slot`): prefer Full only when timely and
/// data available (per `should_extend_payload`). /// data available (per `should_extend_payload`).
/// - Otherwise: prefer Full when payload has been received. /// - Otherwise: prefer Full when payload has been received.
///
/// Returns `None` for V17 nodes. /// Returns `None` for V17 nodes.
pub fn head_payload_status<E: EthSpec>( pub fn head_payload_status<E: EthSpec>(
&self, &self,