mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-18 21:38:31 +00:00
Realized unrealized experimentation (#3322)
## Issue Addressed Add a flag that optionally enables unrealized vote tracking. Would like to test out on testnets and benchmark differences in methods of vote tracking. This PR includes a DB schema upgrade to enable to new vote tracking style. Co-authored-by: realbigsean <sean@sigmaprime.io> Co-authored-by: Paul Hauner <paul@paulhauner.com> Co-authored-by: sean <seananderson33@gmail.com> Co-authored-by: Mac L <mjladson@pm.me>
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
use crate::beacon_fork_choice_store::{PersistedForkChoiceStoreV10, PersistedForkChoiceStoreV8};
|
||||
use crate::persisted_fork_choice::{PersistedForkChoiceV10, PersistedForkChoiceV8};
|
||||
use crate::schema_change::{
|
||||
types::{SszContainerV10, SszContainerV7},
|
||||
StoreError,
|
||||
};
|
||||
use proto_array::core::SszContainer;
|
||||
use ssz::{Decode, Encode};
|
||||
|
||||
pub fn update_fork_choice(
|
||||
mut fork_choice: PersistedForkChoiceV8,
|
||||
) -> Result<PersistedForkChoiceV10, StoreError> {
|
||||
let ssz_container_v7 = SszContainerV7::from_ssz_bytes(
|
||||
&fork_choice.fork_choice.proto_array_bytes,
|
||||
)
|
||||
.map_err(|e| {
|
||||
StoreError::SchemaMigrationError(format!(
|
||||
"Failed to decode ProtoArrayForkChoice during schema migration: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
// These transformations instantiate `node.unrealized_justified_checkpoint` and
|
||||
// `node.unrealized_finalized_checkpoint` to `None`.
|
||||
let ssz_container_v10: SszContainerV10 = ssz_container_v7.into();
|
||||
let ssz_container: SszContainer = ssz_container_v10.into();
|
||||
fork_choice.fork_choice.proto_array_bytes = ssz_container.as_ssz_bytes();
|
||||
|
||||
Ok(fork_choice.into())
|
||||
}
|
||||
|
||||
pub fn downgrade_fork_choice(
|
||||
mut fork_choice: PersistedForkChoiceV10,
|
||||
) -> Result<PersistedForkChoiceV8, StoreError> {
|
||||
let ssz_container_v10 = SszContainerV10::from_ssz_bytes(
|
||||
&fork_choice.fork_choice.proto_array_bytes,
|
||||
)
|
||||
.map_err(|e| {
|
||||
StoreError::SchemaMigrationError(format!(
|
||||
"Failed to decode ProtoArrayForkChoice during schema migration: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
let ssz_container_v7: SszContainerV7 = ssz_container_v10.into();
|
||||
fork_choice.fork_choice.proto_array_bytes = ssz_container_v7.as_ssz_bytes();
|
||||
|
||||
Ok(fork_choice.into())
|
||||
}
|
||||
|
||||
impl From<PersistedForkChoiceStoreV8> for PersistedForkChoiceStoreV10 {
|
||||
fn from(other: PersistedForkChoiceStoreV8) -> Self {
|
||||
Self {
|
||||
balances_cache: other.balances_cache,
|
||||
time: other.time,
|
||||
finalized_checkpoint: other.finalized_checkpoint,
|
||||
justified_checkpoint: other.justified_checkpoint,
|
||||
justified_balances: other.justified_balances,
|
||||
best_justified_checkpoint: other.best_justified_checkpoint,
|
||||
unrealized_justified_checkpoint: other.best_justified_checkpoint,
|
||||
unrealized_finalized_checkpoint: other.finalized_checkpoint,
|
||||
proposer_boost_root: other.proposer_boost_root,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PersistedForkChoiceV8> for PersistedForkChoiceV10 {
|
||||
fn from(other: PersistedForkChoiceV8) -> Self {
|
||||
Self {
|
||||
fork_choice: other.fork_choice,
|
||||
fork_choice_store: other.fork_choice_store.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PersistedForkChoiceStoreV10> for PersistedForkChoiceStoreV8 {
|
||||
fn from(other: PersistedForkChoiceStoreV10) -> Self {
|
||||
Self {
|
||||
balances_cache: other.balances_cache,
|
||||
time: other.time,
|
||||
finalized_checkpoint: other.finalized_checkpoint,
|
||||
justified_checkpoint: other.justified_checkpoint,
|
||||
justified_balances: other.justified_balances,
|
||||
best_justified_checkpoint: other.best_justified_checkpoint,
|
||||
proposer_boost_root: other.proposer_boost_root,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PersistedForkChoiceV10> for PersistedForkChoiceV8 {
|
||||
fn from(other: PersistedForkChoiceV10) -> Self {
|
||||
Self {
|
||||
fork_choice: other.fork_choice,
|
||||
fork_choice_store: other.fork_choice_store.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
use crate::beacon_chain::BeaconChainTypes;
|
||||
use crate::beacon_fork_choice_store::{PersistedForkChoiceStoreV1, PersistedForkChoiceStoreV7};
|
||||
use crate::persisted_fork_choice::{PersistedForkChoiceV1, PersistedForkChoiceV7};
|
||||
use crate::schema_change::types::{ProtoNodeV6, SszContainerV6, SszContainerV7};
|
||||
use crate::schema_change::types::{ProtoNodeV6, SszContainerV10, SszContainerV6, SszContainerV7};
|
||||
use crate::types::{ChainSpec, Checkpoint, Epoch, EthSpec, Hash256, Slot};
|
||||
use crate::{BeaconForkChoiceStore, BeaconSnapshot};
|
||||
use fork_choice::ForkChoice;
|
||||
@@ -86,7 +86,8 @@ pub(crate) fn update_fork_choice<T: BeaconChainTypes>(
|
||||
// to `None`.
|
||||
let ssz_container_v7: SszContainerV7 =
|
||||
ssz_container_v6.into_ssz_container_v7(justified_checkpoint, finalized_checkpoint);
|
||||
let ssz_container: SszContainer = ssz_container_v7.into();
|
||||
let ssz_container_v10: SszContainerV10 = ssz_container_v7.into();
|
||||
let ssz_container: SszContainer = ssz_container_v10.into();
|
||||
let mut fork_choice: ProtoArrayForkChoice = ssz_container.into();
|
||||
|
||||
update_checkpoints::<T>(finalized_checkpoint.root, &nodes_v6, &mut fork_choice, db)
|
||||
@@ -97,6 +98,13 @@ pub(crate) fn update_fork_choice<T: BeaconChainTypes>(
|
||||
update_store_justified_checkpoint(persisted_fork_choice, &mut fork_choice)
|
||||
.map_err(StoreError::SchemaMigrationError)?;
|
||||
|
||||
// Need to downgrade the SSZ container to V7 so that all migrations can be applied in sequence.
|
||||
let ssz_container = SszContainer::from(&fork_choice);
|
||||
let ssz_container_v7 = SszContainerV7::from(ssz_container);
|
||||
|
||||
persisted_fork_choice.fork_choice.proto_array_bytes = ssz_container_v7.as_ssz_bytes();
|
||||
persisted_fork_choice.fork_choice_store.justified_checkpoint = justified_checkpoint;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -301,8 +309,6 @@ fn update_store_justified_checkpoint(
|
||||
.ok_or("Proto node with current finalized checkpoint not found")?;
|
||||
|
||||
fork_choice.core_proto_array_mut().justified_checkpoint = justified_checkpoint;
|
||||
persisted_fork_choice.fork_choice.proto_array_bytes = fork_choice.as_bytes();
|
||||
persisted_fork_choice.fork_choice_store.justified_checkpoint = justified_checkpoint;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ four_byte_option_impl!(four_byte_option_usize, usize);
|
||||
four_byte_option_impl!(four_byte_option_checkpoint, Checkpoint);
|
||||
|
||||
#[superstruct(
|
||||
variants(V1, V6, V7),
|
||||
variants(V1, V6, V7, V10),
|
||||
variant_attributes(derive(Clone, PartialEq, Debug, Encode, Decode)),
|
||||
no_enum
|
||||
)]
|
||||
@@ -30,18 +30,24 @@ pub struct ProtoNode {
|
||||
#[superstruct(only(V1, V6))]
|
||||
pub finalized_epoch: Epoch,
|
||||
#[ssz(with = "four_byte_option_checkpoint")]
|
||||
#[superstruct(only(V7))]
|
||||
#[superstruct(only(V7, V10))]
|
||||
pub justified_checkpoint: Option<Checkpoint>,
|
||||
#[ssz(with = "four_byte_option_checkpoint")]
|
||||
#[superstruct(only(V7))]
|
||||
#[superstruct(only(V7, V10))]
|
||||
pub finalized_checkpoint: Option<Checkpoint>,
|
||||
pub weight: u64,
|
||||
#[ssz(with = "four_byte_option_usize")]
|
||||
pub best_child: Option<usize>,
|
||||
#[ssz(with = "four_byte_option_usize")]
|
||||
pub best_descendant: Option<usize>,
|
||||
#[superstruct(only(V6, V7))]
|
||||
#[superstruct(only(V6, V7, V10))]
|
||||
pub execution_status: ExecutionStatus,
|
||||
#[ssz(with = "four_byte_option_checkpoint")]
|
||||
#[superstruct(only(V10))]
|
||||
pub unrealized_justified_checkpoint: Option<Checkpoint>,
|
||||
#[ssz(with = "four_byte_option_checkpoint")]
|
||||
#[superstruct(only(V10))]
|
||||
pub unrealized_finalized_checkpoint: Option<Checkpoint>,
|
||||
}
|
||||
|
||||
impl Into<ProtoNodeV6> for ProtoNodeV1 {
|
||||
@@ -88,9 +94,31 @@ impl Into<ProtoNodeV7> for ProtoNodeV6 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ProtoNode> for ProtoNodeV7 {
|
||||
fn into(self) -> ProtoNode {
|
||||
ProtoNode {
|
||||
impl Into<ProtoNodeV10> for ProtoNodeV7 {
|
||||
fn into(self) -> ProtoNodeV10 {
|
||||
ProtoNodeV10 {
|
||||
slot: self.slot,
|
||||
state_root: self.state_root,
|
||||
target_root: self.target_root,
|
||||
current_epoch_shuffling_id: self.current_epoch_shuffling_id,
|
||||
next_epoch_shuffling_id: self.next_epoch_shuffling_id,
|
||||
root: self.root,
|
||||
parent: self.parent,
|
||||
justified_checkpoint: self.justified_checkpoint,
|
||||
finalized_checkpoint: self.finalized_checkpoint,
|
||||
weight: self.weight,
|
||||
best_child: self.best_child,
|
||||
best_descendant: self.best_descendant,
|
||||
execution_status: self.execution_status,
|
||||
unrealized_justified_checkpoint: None,
|
||||
unrealized_finalized_checkpoint: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ProtoNodeV7> for ProtoNodeV10 {
|
||||
fn into(self) -> ProtoNodeV7 {
|
||||
ProtoNodeV7 {
|
||||
slot: self.slot,
|
||||
state_root: self.state_root,
|
||||
target_root: self.target_root,
|
||||
@@ -108,8 +136,50 @@ impl Into<ProtoNode> for ProtoNodeV7 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ProtoNode> for ProtoNodeV10 {
|
||||
fn into(self) -> ProtoNode {
|
||||
ProtoNode {
|
||||
slot: self.slot,
|
||||
state_root: self.state_root,
|
||||
target_root: self.target_root,
|
||||
current_epoch_shuffling_id: self.current_epoch_shuffling_id,
|
||||
next_epoch_shuffling_id: self.next_epoch_shuffling_id,
|
||||
root: self.root,
|
||||
parent: self.parent,
|
||||
justified_checkpoint: self.justified_checkpoint,
|
||||
finalized_checkpoint: self.finalized_checkpoint,
|
||||
weight: self.weight,
|
||||
best_child: self.best_child,
|
||||
best_descendant: self.best_descendant,
|
||||
execution_status: self.execution_status,
|
||||
unrealized_justified_checkpoint: self.unrealized_justified_checkpoint,
|
||||
unrealized_finalized_checkpoint: self.unrealized_finalized_checkpoint,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProtoNode> for ProtoNodeV7 {
|
||||
fn from(container: ProtoNode) -> Self {
|
||||
Self {
|
||||
slot: container.slot,
|
||||
state_root: container.state_root,
|
||||
target_root: container.target_root,
|
||||
current_epoch_shuffling_id: container.current_epoch_shuffling_id,
|
||||
next_epoch_shuffling_id: container.next_epoch_shuffling_id,
|
||||
root: container.root,
|
||||
parent: container.parent,
|
||||
justified_checkpoint: container.justified_checkpoint,
|
||||
finalized_checkpoint: container.finalized_checkpoint,
|
||||
weight: container.weight,
|
||||
best_child: container.best_child,
|
||||
best_descendant: container.best_descendant,
|
||||
execution_status: container.execution_status,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[superstruct(
|
||||
variants(V1, V6, V7),
|
||||
variants(V1, V6, V7, V10),
|
||||
variant_attributes(derive(Encode, Decode)),
|
||||
no_enum
|
||||
)]
|
||||
@@ -122,9 +192,9 @@ pub struct SszContainer {
|
||||
pub justified_epoch: Epoch,
|
||||
#[superstruct(only(V1, V6))]
|
||||
pub finalized_epoch: Epoch,
|
||||
#[superstruct(only(V7))]
|
||||
#[superstruct(only(V7, V10))]
|
||||
pub justified_checkpoint: Checkpoint,
|
||||
#[superstruct(only(V7))]
|
||||
#[superstruct(only(V7, V10))]
|
||||
pub finalized_checkpoint: Checkpoint,
|
||||
#[superstruct(only(V1))]
|
||||
pub nodes: Vec<ProtoNodeV1>,
|
||||
@@ -132,8 +202,10 @@ pub struct SszContainer {
|
||||
pub nodes: Vec<ProtoNodeV6>,
|
||||
#[superstruct(only(V7))]
|
||||
pub nodes: Vec<ProtoNodeV7>,
|
||||
#[superstruct(only(V10))]
|
||||
pub nodes: Vec<ProtoNodeV10>,
|
||||
pub indices: Vec<(Hash256, usize)>,
|
||||
#[superstruct(only(V7))]
|
||||
#[superstruct(only(V7, V10))]
|
||||
pub previous_proposer_boost: ProposerBoost,
|
||||
}
|
||||
|
||||
@@ -174,7 +246,41 @@ impl SszContainerV6 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<SszContainer> for SszContainerV7 {
|
||||
impl Into<SszContainerV10> for SszContainerV7 {
|
||||
fn into(self) -> SszContainerV10 {
|
||||
let nodes = self.nodes.into_iter().map(Into::into).collect();
|
||||
|
||||
SszContainerV10 {
|
||||
votes: self.votes,
|
||||
balances: self.balances,
|
||||
prune_threshold: self.prune_threshold,
|
||||
justified_checkpoint: self.justified_checkpoint,
|
||||
finalized_checkpoint: self.finalized_checkpoint,
|
||||
nodes,
|
||||
indices: self.indices,
|
||||
previous_proposer_boost: self.previous_proposer_boost,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<SszContainerV7> for SszContainerV10 {
|
||||
fn into(self) -> SszContainerV7 {
|
||||
let nodes = self.nodes.into_iter().map(Into::into).collect();
|
||||
|
||||
SszContainerV7 {
|
||||
votes: self.votes,
|
||||
balances: self.balances,
|
||||
prune_threshold: self.prune_threshold,
|
||||
justified_checkpoint: self.justified_checkpoint,
|
||||
finalized_checkpoint: self.finalized_checkpoint,
|
||||
nodes,
|
||||
indices: self.indices,
|
||||
previous_proposer_boost: self.previous_proposer_boost,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<SszContainer> for SszContainerV10 {
|
||||
fn into(self) -> SszContainer {
|
||||
let nodes = self.nodes.into_iter().map(Into::into).collect();
|
||||
|
||||
@@ -190,3 +296,20 @@ impl Into<SszContainer> for SszContainerV7 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SszContainer> for SszContainerV7 {
|
||||
fn from(container: SszContainer) -> Self {
|
||||
let nodes = container.nodes.into_iter().map(Into::into).collect();
|
||||
|
||||
Self {
|
||||
votes: container.votes,
|
||||
balances: container.balances,
|
||||
prune_threshold: container.prune_threshold,
|
||||
justified_checkpoint: container.justified_checkpoint,
|
||||
finalized_checkpoint: container.finalized_checkpoint,
|
||||
nodes,
|
||||
indices: container.indices,
|
||||
previous_proposer_boost: container.previous_proposer_boost,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user