mirror of
https://github.com/sigp/lighthouse.git
synced 2026-05-30 20:57:10 +00:00
Fix more issues (mainly payload attestation application)
This commit is contained in:
@@ -685,7 +685,7 @@ impl ProtoArray {
|
|||||||
/// Returns `true` if the proposer boost should be kept. Returns `false` if the
|
/// Returns `true` if the proposer boost should be kept. Returns `false` if the
|
||||||
/// boost should be subtracted (invalidated) because the parent is weak and there
|
/// boost should be subtracted (invalidated) because the parent is weak and there
|
||||||
/// are no equivocating blocks at the parent's slot.
|
/// are no equivocating blocks at the parent's slot.
|
||||||
fn should_apply_proposer_boost<E: EthSpec>(
|
pub(crate) fn should_apply_proposer_boost<E: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
proposer_boost_root: Hash256,
|
proposer_boost_root: Hash256,
|
||||||
justified_balances: &JustifiedBalances,
|
justified_balances: &JustifiedBalances,
|
||||||
@@ -1328,7 +1328,7 @@ impl ProtoArray {
|
|||||||
|
|
||||||
/// Spec: `get_weight`.
|
/// Spec: `get_weight`.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn get_weight<E: EthSpec>(
|
pub(crate) fn get_weight<E: EthSpec>(
|
||||||
&self,
|
&self,
|
||||||
fc_node: &IndexedForkChoiceNode,
|
fc_node: &IndexedForkChoiceNode,
|
||||||
proto_node: &ProtoNode,
|
proto_node: &ProtoNode,
|
||||||
|
|||||||
@@ -1089,7 +1089,10 @@ impl ProtoArrayForkChoice {
|
|||||||
current_slot: Slot,
|
current_slot: Slot,
|
||||||
justified_checkpoint: Checkpoint,
|
justified_checkpoint: Checkpoint,
|
||||||
finalized_checkpoint: Checkpoint,
|
finalized_checkpoint: Checkpoint,
|
||||||
) -> Result<Vec<(Hash256, u64)>, String> {
|
proposer_boost_root: Hash256,
|
||||||
|
justified_balances: &JustifiedBalances,
|
||||||
|
spec: &ChainSpec,
|
||||||
|
) -> Result<Vec<(Hash256, PayloadStatus, u64)>, String> {
|
||||||
let start_index = self
|
let start_index = self
|
||||||
.proto_array
|
.proto_array
|
||||||
.indices
|
.indices
|
||||||
@@ -1107,6 +1110,12 @@ impl ProtoArrayForkChoice {
|
|||||||
justified_checkpoint,
|
justified_checkpoint,
|
||||||
finalized_checkpoint,
|
finalized_checkpoint,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let apply_proposer_boost = self
|
||||||
|
.proto_array
|
||||||
|
.should_apply_proposer_boost::<E>(proposer_boost_root, justified_balances, spec)
|
||||||
|
.map_err(|e| format!("should_apply_proposer_boost failed: {e:?}"))?;
|
||||||
|
|
||||||
let mut leaves = Vec::with_capacity(viable.len());
|
let mut leaves = Vec::with_capacity(viable.len());
|
||||||
for &i in &viable {
|
for &i in &viable {
|
||||||
let has_viable_child = viable
|
let has_viable_child = viable
|
||||||
@@ -1120,7 +1129,70 @@ impl ProtoArrayForkChoice {
|
|||||||
.nodes
|
.nodes
|
||||||
.get(i)
|
.get(i)
|
||||||
.ok_or_else(|| format!("invalid viable node index {i}"))?;
|
.ok_or_else(|| format!("invalid viable node index {i}"))?;
|
||||||
leaves.push((node.root(), node.weight()));
|
|
||||||
|
let is_gloas = node.payload_received().is_ok();
|
||||||
|
if is_gloas {
|
||||||
|
// Gloas: expand into Empty/Full virtual children.
|
||||||
|
let empty_fc = IndexedForkChoiceNode {
|
||||||
|
root: node.root(),
|
||||||
|
proto_node_index: i,
|
||||||
|
payload_status: PayloadStatus::Empty,
|
||||||
|
};
|
||||||
|
let empty_weight = self
|
||||||
|
.proto_array
|
||||||
|
.get_weight::<E>(
|
||||||
|
&empty_fc,
|
||||||
|
node,
|
||||||
|
apply_proposer_boost,
|
||||||
|
proposer_boost_root,
|
||||||
|
current_slot,
|
||||||
|
justified_balances,
|
||||||
|
spec,
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("get_weight failed: {e:?}"))?;
|
||||||
|
leaves.push((node.root(), PayloadStatus::Empty, empty_weight));
|
||||||
|
|
||||||
|
if node.payload_received().is_ok_and(|r| r) {
|
||||||
|
let full_fc = IndexedForkChoiceNode {
|
||||||
|
root: node.root(),
|
||||||
|
proto_node_index: i,
|
||||||
|
payload_status: PayloadStatus::Full,
|
||||||
|
};
|
||||||
|
let full_weight = self
|
||||||
|
.proto_array
|
||||||
|
.get_weight::<E>(
|
||||||
|
&full_fc,
|
||||||
|
node,
|
||||||
|
apply_proposer_boost,
|
||||||
|
proposer_boost_root,
|
||||||
|
current_slot,
|
||||||
|
justified_balances,
|
||||||
|
spec,
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("get_weight failed: {e:?}"))?;
|
||||||
|
leaves.push((node.root(), PayloadStatus::Full, full_weight));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Pre-Gloas: use Pending status (no payload split).
|
||||||
|
let fc_node = IndexedForkChoiceNode {
|
||||||
|
root: node.root(),
|
||||||
|
proto_node_index: i,
|
||||||
|
payload_status: PayloadStatus::Pending,
|
||||||
|
};
|
||||||
|
let weight = self
|
||||||
|
.proto_array
|
||||||
|
.get_weight::<E>(
|
||||||
|
&fc_node,
|
||||||
|
node,
|
||||||
|
apply_proposer_boost,
|
||||||
|
proposer_boost_root,
|
||||||
|
current_slot,
|
||||||
|
justified_balances,
|
||||||
|
spec,
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("get_weight failed: {e:?}"))?;
|
||||||
|
leaves.push((node.root(), PayloadStatus::Pending, weight));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(leaves)
|
Ok(leaves)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::decode::{ssz_decode_file, ssz_decode_file_with, ssz_decode_state, yaml_decode_file};
|
use crate::decode::{ssz_decode_file, ssz_decode_file_with, ssz_decode_state, yaml_decode_file};
|
||||||
use ::fork_choice::{
|
use ::fork_choice::{
|
||||||
AttestationFromBlock, ForkChoiceStore, PayloadVerificationStatus, ProposerHeadError,
|
AttestationFromBlock, ForkChoiceStore, PayloadStatus as FcPayloadStatus,
|
||||||
|
PayloadVerificationStatus, ProposerHeadError,
|
||||||
};
|
};
|
||||||
use beacon_chain::beacon_proposer_cache::compute_proposer_duties_from_head;
|
use beacon_chain::beacon_proposer_cache::compute_proposer_duties_from_head;
|
||||||
use beacon_chain::blob_verification::GossipBlobError;
|
use beacon_chain::blob_verification::GossipBlobError;
|
||||||
@@ -85,10 +86,10 @@ pub struct Checks {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct RootAndWeight {
|
pub struct RootAndWeight {
|
||||||
pub root: Hash256,
|
pub root: Hash256,
|
||||||
pub weight: u64,
|
pub weight: u64,
|
||||||
|
pub payload_status: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
@@ -624,10 +625,7 @@ impl<E: EthSpec> Tester<E> {
|
|||||||
.slot_clock
|
.slot_clock
|
||||||
.set_current_time(Duration::from_secs(tick));
|
.set_current_time(Duration::from_secs(tick));
|
||||||
|
|
||||||
// Compute the slot time manually to ensure the slot clock is correct.
|
|
||||||
let slot = self.tick_to_slot(tick).unwrap();
|
let slot = self.tick_to_slot(tick).unwrap();
|
||||||
assert_eq!(slot, self.harness.chain.slot().unwrap());
|
|
||||||
|
|
||||||
self.harness
|
self.harness
|
||||||
.chain
|
.chain
|
||||||
.canonical_head
|
.canonical_head
|
||||||
@@ -920,11 +918,15 @@ impl<E: EthSpec> Tester<E> {
|
|||||||
signature: AggregateSignature::from(&message.signature),
|
signature: AggregateSignature::from(&message.signature),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let current_slot = self.harness.chain.slot().map_err(|e| {
|
||||||
|
Error::InternalError(format!("reading current slot failed with {:?}", e))
|
||||||
|
})?;
|
||||||
|
|
||||||
self.harness
|
self.harness
|
||||||
.chain
|
.chain
|
||||||
.canonical_head
|
.canonical_head
|
||||||
.fork_choice_write_lock()
|
.fork_choice_write_lock()
|
||||||
.on_payload_attestation(slot, &indexed, AttestationFromBlock::False, &ptc.0)
|
.on_payload_attestation(current_slot, &indexed, AttestationFromBlock::False, &ptc.0)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
Error::InternalError(format!("payload attestation import failed with {:?}", e))
|
Error::InternalError(format!("payload attestation import failed with {:?}", e))
|
||||||
})
|
})
|
||||||
@@ -1220,6 +1222,8 @@ impl<E: EthSpec> Tester<E> {
|
|||||||
let justified = fork_choice.justified_checkpoint();
|
let justified = fork_choice.justified_checkpoint();
|
||||||
let finalized = fork_choice.finalized_checkpoint();
|
let finalized = fork_choice.finalized_checkpoint();
|
||||||
let current_slot = fork_choice.fc_store().get_current_slot();
|
let current_slot = fork_choice.fc_store().get_current_slot();
|
||||||
|
let proposer_boost_root = fork_choice.proposer_boost_root();
|
||||||
|
let justified_balances = fork_choice.fc_store().justified_balances().clone();
|
||||||
let actual = fork_choice
|
let actual = fork_choice
|
||||||
.proto_array()
|
.proto_array()
|
||||||
.filtered_block_tree_leaves_and_weights::<E>(
|
.filtered_block_tree_leaves_and_weights::<E>(
|
||||||
@@ -1227,6 +1231,9 @@ impl<E: EthSpec> Tester<E> {
|
|||||||
current_slot,
|
current_slot,
|
||||||
justified,
|
justified,
|
||||||
finalized,
|
finalized,
|
||||||
|
proposer_boost_root,
|
||||||
|
&justified_balances,
|
||||||
|
&self.spec,
|
||||||
)
|
)
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
Error::InternalError(format!(
|
Error::InternalError(format!(
|
||||||
@@ -1235,10 +1242,15 @@ impl<E: EthSpec> Tester<E> {
|
|||||||
})?;
|
})?;
|
||||||
drop(fork_choice);
|
drop(fork_choice);
|
||||||
|
|
||||||
let mut actual_sorted = actual;
|
let mut actual_sorted: Vec<(Hash256, u8, u64)> = actual
|
||||||
|
.into_iter()
|
||||||
|
.map(|(root, status, weight)| (root, status as u8, weight))
|
||||||
|
.collect();
|
||||||
actual_sorted.sort();
|
actual_sorted.sort();
|
||||||
let mut expected_sorted: Vec<(Hash256, u64)> =
|
let mut expected_sorted: Vec<(Hash256, u8, u64)> = expected
|
||||||
expected.iter().map(|x| (x.root, x.weight)).collect();
|
.iter()
|
||||||
|
.map(|x| (x.root, x.payload_status.unwrap_or(FcPayloadStatus::Pending as u8), x.weight))
|
||||||
|
.collect();
|
||||||
expected_sorted.sort();
|
expected_sorted.sort();
|
||||||
|
|
||||||
check_equal(
|
check_equal(
|
||||||
|
|||||||
@@ -748,7 +748,6 @@ impl<E: EthSpec + TypeName> Handler for ForkChoiceHandler<E> {
|
|||||||
|
|
||||||
pub struct ForkChoiceComplianceHandler<E> {
|
pub struct ForkChoiceComplianceHandler<E> {
|
||||||
handler_name: String,
|
handler_name: String,
|
||||||
only_fork: Option<ForkName>,
|
|
||||||
_phantom: PhantomData<E>,
|
_phantom: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -756,7 +755,6 @@ impl<E: EthSpec> ForkChoiceComplianceHandler<E> {
|
|||||||
pub fn new(handler_name: &str) -> Self {
|
pub fn new(handler_name: &str) -> Self {
|
||||||
Self {
|
Self {
|
||||||
handler_name: handler_name.into(),
|
handler_name: handler_name.into(),
|
||||||
only_fork: None,
|
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user