mirror of
https://github.com/sigp/lighthouse.git
synced 2026-07-04 13:24:39 +00:00
Fix compilation, clear best_child/best_descendant in migration
- Fix leaf detection in heads_descended_from_finalization (parent() method call, map away enumerate index) - Clear best_child and best_descendant in v28->v29 migration (no longer used, replaced by virtual tree walk) - Migration now rewrites fork choice data instead of being a no-op
This commit is contained in:
@@ -2,17 +2,18 @@ use crate::beacon_chain::BeaconChainTypes;
|
|||||||
use crate::persisted_fork_choice::{PersistedForkChoiceV28, PersistedForkChoiceV29};
|
use crate::persisted_fork_choice::{PersistedForkChoiceV28, PersistedForkChoiceV29};
|
||||||
use ssz::Decode;
|
use ssz::Decode;
|
||||||
use store::hot_cold_store::HotColdDB;
|
use store::hot_cold_store::HotColdDB;
|
||||||
use store::{DBColumn, Error as StoreError, KeyValueStore};
|
use store::{DBColumn, Error as StoreError, KeyValueStore, KeyValueStoreOp};
|
||||||
use types::{EthSpec, Hash256};
|
use types::{EthSpec, Hash256};
|
||||||
|
|
||||||
/// The key used to store the fork choice in the database.
|
/// The key used to store the fork choice in the database.
|
||||||
const FORK_CHOICE_DB_KEY: Hash256 = Hash256::ZERO;
|
const FORK_CHOICE_DB_KEY: Hash256 = Hash256::ZERO;
|
||||||
|
|
||||||
/// Upgrade from schema v28 to v29 (no-op).
|
/// Upgrade from schema v28 to v29.
|
||||||
///
|
///
|
||||||
/// Fails if the persisted fork choice contains any V17 (pre-Gloas) proto nodes at or after the
|
/// - Clears `best_child` and `best_descendant` on all nodes (replaced by
|
||||||
/// Gloas fork slot. Such nodes indicate the node synced a broken sidechain with Gloas disabled
|
/// virtual tree walk).
|
||||||
/// and would not be able to sync the v29 chain.
|
/// - Fails if the persisted fork choice contains any V17 (pre-Gloas) proto
|
||||||
|
/// nodes at or after the Gloas fork slot.
|
||||||
pub fn upgrade_to_v29<T: BeaconChainTypes>(
|
pub fn upgrade_to_v29<T: BeaconChainTypes>(
|
||||||
db: &HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>,
|
db: &HotColdDB<T::EthSpec, T::HotStore, T::ColdStore>,
|
||||||
) -> Result<(), StoreError> {
|
) -> Result<(), StoreError> {
|
||||||
@@ -21,11 +22,6 @@ pub fn upgrade_to_v29<T: BeaconChainTypes>(
|
|||||||
.gloas_fork_epoch
|
.gloas_fork_epoch
|
||||||
.map(|epoch| epoch.start_slot(T::EthSpec::slots_per_epoch()));
|
.map(|epoch| epoch.start_slot(T::EthSpec::slots_per_epoch()));
|
||||||
|
|
||||||
// If Gloas is not configured, the upgrade is a safe no-op.
|
|
||||||
let Some(gloas_fork_slot) = gloas_fork_slot else {
|
|
||||||
return Ok(());
|
|
||||||
};
|
|
||||||
|
|
||||||
// Load the persisted fork choice (v28 format, uncompressed SSZ).
|
// Load the persisted fork choice (v28 format, uncompressed SSZ).
|
||||||
let Some(fc_bytes) = db
|
let Some(fc_bytes) = db
|
||||||
.hot_db
|
.hot_db
|
||||||
@@ -34,26 +30,45 @@ pub fn upgrade_to_v29<T: BeaconChainTypes>(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let persisted_v28 =
|
let mut persisted_v28 =
|
||||||
PersistedForkChoiceV28::from_ssz_bytes(&fc_bytes).map_err(StoreError::SszDecodeError)?;
|
PersistedForkChoiceV28::from_ssz_bytes(&fc_bytes).map_err(StoreError::SszDecodeError)?;
|
||||||
|
|
||||||
// In v28 format, all nodes are ProtoNodeV17. Check if any are at/after the Gloas fork slot.
|
// Check for V17 nodes at/after the Gloas fork slot.
|
||||||
let bad_node = persisted_v28
|
if let Some(gloas_fork_slot) = gloas_fork_slot {
|
||||||
.fork_choice_v28
|
let bad_node = persisted_v28
|
||||||
.proto_array_v28
|
.fork_choice_v28
|
||||||
.nodes
|
.proto_array_v28
|
||||||
.iter()
|
.nodes
|
||||||
.find(|node| node.slot >= gloas_fork_slot);
|
.iter()
|
||||||
|
.find(|node| node.slot >= gloas_fork_slot);
|
||||||
|
|
||||||
if let Some(node) = bad_node {
|
if let Some(node) = bad_node {
|
||||||
return Err(StoreError::MigrationError(format!(
|
return Err(StoreError::MigrationError(format!(
|
||||||
"cannot upgrade from v28 to v29: found V17 proto node at slot {} (root: {:?}) \
|
"cannot upgrade from v28 to v29: found V17 proto node at slot {} (root: {:?}) \
|
||||||
which is at or after the Gloas fork slot {}. This node has synced a chain with \
|
which is at or after the Gloas fork slot {}. This node has synced a chain with \
|
||||||
Gloas disabled and cannot be upgraded. Please resync from scratch.",
|
Gloas disabled and cannot be upgraded. Please resync from scratch.",
|
||||||
node.slot, node.root, gloas_fork_slot,
|
node.slot, node.root, gloas_fork_slot,
|
||||||
)));
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear best_child/best_descendant — replaced by the virtual tree walk.
|
||||||
|
for node in &mut persisted_v28.fork_choice_v28.proto_array_v28.nodes {
|
||||||
|
node.best_child = None;
|
||||||
|
node.best_descendant = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert to v29 and write back.
|
||||||
|
let persisted_v29 = PersistedForkChoiceV29::from(persisted_v28);
|
||||||
|
let fc_bytes = persisted_v29
|
||||||
|
.as_bytes(db.get_config())
|
||||||
|
.map_err(|e| StoreError::MigrationError(format!("failed to encode v29: {:?}", e)))?;
|
||||||
|
db.hot_db.do_atomically(vec![KeyValueStoreOp::PutKeyValue(
|
||||||
|
DBColumn::ForkChoice,
|
||||||
|
FORK_CHOICE_DB_KEY.as_slice().to_vec(),
|
||||||
|
fc_bytes,
|
||||||
|
)])?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1008,8 +1008,6 @@ where
|
|||||||
proposer_index: Some(block.proposer_index()),
|
proposer_index: Some(block.proposer_index()),
|
||||||
},
|
},
|
||||||
current_slot,
|
current_slot,
|
||||||
self.justified_checkpoint(),
|
|
||||||
self.finalized_checkpoint(),
|
|
||||||
spec,
|
spec,
|
||||||
block_delay,
|
block_delay,
|
||||||
)?;
|
)?;
|
||||||
|
|||||||
@@ -283,14 +283,7 @@ impl ForkChoiceTestDefinition {
|
|||||||
proposer_index: Some(0),
|
proposer_index: Some(0),
|
||||||
};
|
};
|
||||||
fork_choice
|
fork_choice
|
||||||
.process_block::<MainnetEthSpec>(
|
.process_block::<MainnetEthSpec>(block, slot, &spec, Duration::ZERO)
|
||||||
block,
|
|
||||||
slot,
|
|
||||||
self.justified_checkpoint,
|
|
||||||
self.finalized_checkpoint,
|
|
||||||
&spec,
|
|
||||||
Duration::ZERO,
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|e| {
|
.unwrap_or_else(|e| {
|
||||||
panic!(
|
panic!(
|
||||||
"process_block op at index {} returned error: {:?}",
|
"process_block op at index {} returned error: {:?}",
|
||||||
|
|||||||
@@ -389,9 +389,6 @@ impl ProtoArray {
|
|||||||
pub fn apply_score_changes<E: EthSpec>(
|
pub fn apply_score_changes<E: EthSpec>(
|
||||||
&mut self,
|
&mut self,
|
||||||
mut deltas: Vec<NodeDelta>,
|
mut deltas: Vec<NodeDelta>,
|
||||||
best_justified_checkpoint: Checkpoint,
|
|
||||||
best_finalized_checkpoint: Checkpoint,
|
|
||||||
current_slot: Slot,
|
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
if deltas.len() != self.indices.len() {
|
if deltas.len() != self.indices.len() {
|
||||||
return Err(Error::InvalidDeltaLen {
|
return Err(Error::InvalidDeltaLen {
|
||||||
@@ -518,8 +515,6 @@ impl ProtoArray {
|
|||||||
&mut self,
|
&mut self,
|
||||||
block: Block,
|
block: Block,
|
||||||
current_slot: Slot,
|
current_slot: Slot,
|
||||||
best_justified_checkpoint: Checkpoint,
|
|
||||||
best_finalized_checkpoint: Checkpoint,
|
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
time_into_slot: Duration,
|
time_into_slot: Duration,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
@@ -677,10 +672,10 @@ impl ProtoArray {
|
|||||||
self.indices.insert(node.root(), node_index);
|
self.indices.insert(node.root(), node_index);
|
||||||
self.nodes.push(node.clone());
|
self.nodes.push(node.clone());
|
||||||
|
|
||||||
if let Some(parent_index) = node.parent() {
|
if let Some(parent_index) = node.parent()
|
||||||
if matches!(block.execution_status, ExecutionStatus::Valid(_)) {
|
&& matches!(block.execution_status, ExecutionStatus::Valid(_))
|
||||||
self.propagate_execution_payload_validation_by_index(parent_index)?;
|
{
|
||||||
}
|
self.propagate_execution_payload_validation_by_index(parent_index)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -1773,17 +1768,14 @@ impl ProtoArray {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|(i, node)| {
|
.filter(|(i, node)| {
|
||||||
// TODO(gloas): we unoptimized this for Gloas fork choice, could re-optimize.
|
// TODO(gloas): we unoptimized this for Gloas fork choice, could re-optimize.
|
||||||
let num_children = self
|
let num_children = self.nodes.iter().filter(|n| n.parent() == Some(*i)).count();
|
||||||
.nodes
|
|
||||||
.iter()
|
|
||||||
.filter(|node| node.parent == Some(i))
|
|
||||||
.count();
|
|
||||||
num_children == 0
|
num_children == 0
|
||||||
&& self.is_finalized_checkpoint_or_descendant::<E>(
|
&& self.is_finalized_checkpoint_or_descendant::<E>(
|
||||||
node.root(),
|
node.root(),
|
||||||
best_finalized_checkpoint,
|
best_finalized_checkpoint,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
.map(|(_, node)| node)
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -512,8 +512,6 @@ impl ProtoArrayForkChoice {
|
|||||||
.on_block::<E>(
|
.on_block::<E>(
|
||||||
block,
|
block,
|
||||||
current_slot,
|
current_slot,
|
||||||
justified_checkpoint,
|
|
||||||
finalized_checkpoint,
|
|
||||||
spec,
|
spec,
|
||||||
// Anchor block is always timely (delay=0 ensures both timeliness
|
// Anchor block is always timely (delay=0 ensures both timeliness
|
||||||
// checks pass). Combined with `is_genesis` override in on_block,
|
// checks pass). Combined with `is_genesis` override in on_block,
|
||||||
@@ -615,8 +613,6 @@ impl ProtoArrayForkChoice {
|
|||||||
&mut self,
|
&mut self,
|
||||||
block: Block,
|
block: Block,
|
||||||
current_slot: Slot,
|
current_slot: Slot,
|
||||||
justified_checkpoint: Checkpoint,
|
|
||||||
finalized_checkpoint: Checkpoint,
|
|
||||||
spec: &ChainSpec,
|
spec: &ChainSpec,
|
||||||
time_into_slot: Duration,
|
time_into_slot: Duration,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
@@ -625,14 +621,7 @@ impl ProtoArrayForkChoice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.proto_array
|
self.proto_array
|
||||||
.on_block::<E>(
|
.on_block::<E>(block, current_slot, spec, time_into_slot)
|
||||||
block,
|
|
||||||
current_slot,
|
|
||||||
justified_checkpoint,
|
|
||||||
finalized_checkpoint,
|
|
||||||
spec,
|
|
||||||
time_into_slot,
|
|
||||||
)
|
|
||||||
.map_err(|e| format!("process_block_error: {:?}", e))
|
.map_err(|e| format!("process_block_error: {:?}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,12 +656,7 @@ impl ProtoArrayForkChoice {
|
|||||||
.map_err(|e| format!("find_head compute_deltas failed: {:?}", e))?;
|
.map_err(|e| format!("find_head compute_deltas failed: {:?}", e))?;
|
||||||
|
|
||||||
self.proto_array
|
self.proto_array
|
||||||
.apply_score_changes::<E>(
|
.apply_score_changes::<E>(deltas)
|
||||||
deltas,
|
|
||||||
justified_checkpoint,
|
|
||||||
finalized_checkpoint,
|
|
||||||
current_slot,
|
|
||||||
)
|
|
||||||
.map_err(|e| format!("find_head apply_score_changes failed: {:?}", e))?;
|
.map_err(|e| format!("find_head apply_score_changes failed: {:?}", e))?;
|
||||||
|
|
||||||
*old_balances = new_balances.clone();
|
*old_balances = new_balances.clone();
|
||||||
@@ -1354,8 +1338,6 @@ mod test_compute_deltas {
|
|||||||
proposer_index: Some(0),
|
proposer_index: Some(0),
|
||||||
},
|
},
|
||||||
genesis_slot + 1,
|
genesis_slot + 1,
|
||||||
genesis_checkpoint,
|
|
||||||
genesis_checkpoint,
|
|
||||||
&spec,
|
&spec,
|
||||||
Duration::ZERO,
|
Duration::ZERO,
|
||||||
)
|
)
|
||||||
@@ -1384,8 +1366,6 @@ mod test_compute_deltas {
|
|||||||
proposer_index: Some(0),
|
proposer_index: Some(0),
|
||||||
},
|
},
|
||||||
genesis_slot + 1,
|
genesis_slot + 1,
|
||||||
genesis_checkpoint,
|
|
||||||
genesis_checkpoint,
|
|
||||||
&spec,
|
&spec,
|
||||||
Duration::ZERO,
|
Duration::ZERO,
|
||||||
)
|
)
|
||||||
@@ -1521,8 +1501,6 @@ mod test_compute_deltas {
|
|||||||
proposer_index: Some(0),
|
proposer_index: Some(0),
|
||||||
},
|
},
|
||||||
Slot::from(block.slot),
|
Slot::from(block.slot),
|
||||||
genesis_checkpoint,
|
|
||||||
genesis_checkpoint,
|
|
||||||
&spec,
|
&spec,
|
||||||
Duration::ZERO,
|
Duration::ZERO,
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user