diff --git a/beacon_node/beacon_chain/src/schema_change/migration_schema_v29.rs b/beacon_node/beacon_chain/src/schema_change/migration_schema_v29.rs index 77d4be3443e..502242db596 100644 --- a/beacon_node/beacon_chain/src/schema_change/migration_schema_v29.rs +++ b/beacon_node/beacon_chain/src/schema_change/migration_schema_v29.rs @@ -57,8 +57,23 @@ pub fn upgrade_to_v29( .proto_array_v28 .previous_proposer_boost; - // Convert to v29. - let mut persisted_v29 = PersistedForkChoiceV29::from(persisted_v28); + let PersistedForkChoiceV28 { + fork_choice_v28, + fork_choice_store, + } = persisted_v28; + let fork_choice::PersistedForkChoiceV28 { + proto_array_v28, + queued_attestations_v28: _, + } = fork_choice_v28; + let mut persisted_v29 = PersistedForkChoiceV29 { + fork_choice: fork_choice::PersistedForkChoiceV29 { + proto_array: proto_array::core::SszContainerV29::from_v28_with_slots_per_epoch( + proto_array_v28, + T::EthSpec::slots_per_epoch(), + ), + }, + fork_choice_store, + }; // Subtract the proposer boost from the boosted node and all its ancestors. // diff --git a/consensus/proto_array/src/proto_array_fork_choice.rs b/consensus/proto_array/src/proto_array_fork_choice.rs index 7aee9b16264..45a7209a709 100644 --- a/consensus/proto_array/src/proto_array_fork_choice.rs +++ b/consensus/proto_array/src/proto_array_fork_choice.rs @@ -53,6 +53,30 @@ impl VoteTracker { } } +impl VoteTrackerV28 { + pub fn into_v29_with_slots_per_epoch(self, slots_per_epoch: u64) -> VoteTracker { + let next_slot = if self.next_root.is_zero() { + Slot::new(0) + } else { + self.next_epoch.start_slot(slots_per_epoch) + }; + let current_slot = if self.current_root == self.next_root { + next_slot + } else { + Slot::new(0) + }; + + VoteTracker { + current_root: self.current_root, + next_root: self.next_root, + current_slot, + next_slot, + current_payload_present: false, + next_payload_present: false, + } + } +} + // This impl is only used upon upgrade from pre-Gloas to Gloas with all pre-Gloas nodes. // The payload status is `false` for pre-Gloas nodes. impl From for VoteTracker { @@ -1347,6 +1371,37 @@ mod test_compute_deltas { vec![Slot::new(0); count] } + #[test] + fn v28_vote_conversion_preserves_latest_message_epoch() { + let root = hash_from_index(1); + let vote = VoteTrackerV28 { + current_root: root, + next_root: root, + next_epoch: Epoch::new(2), + }; + + let converted = vote.into_v29_with_slots_per_epoch(MainnetEthSpec::slots_per_epoch()); + + assert_eq!(converted.current_root, root); + assert_eq!(converted.next_root, root); + assert_eq!(converted.current_slot, Slot::new(64)); + assert_eq!(converted.next_slot, Slot::new(64)); + } + + #[test] + fn v28_vote_conversion_only_sets_next_slot_for_pending_vote() { + let vote = VoteTrackerV28 { + current_root: hash_from_index(1), + next_root: hash_from_index(2), + next_epoch: Epoch::new(2), + }; + + let converted = vote.into_v29_with_slots_per_epoch(MainnetEthSpec::slots_per_epoch()); + + assert_eq!(converted.current_slot, Slot::new(0)); + assert_eq!(converted.next_slot, Slot::new(64)); + } + #[test] fn finalized_descendant() { let spec = MainnetEthSpec::default_spec(); diff --git a/consensus/proto_array/src/ssz_container.rs b/consensus/proto_array/src/ssz_container.rs index ec70e88a730..2f2b46789f9 100644 --- a/consensus/proto_array/src/ssz_container.rs +++ b/consensus/proto_array/src/ssz_container.rs @@ -53,6 +53,27 @@ impl SszContainerV29 { indices: proto_array.indices.iter().map(|(k, v)| (*k, *v)).collect(), } } + + pub fn from_v28_with_slots_per_epoch(v28: SszContainerV28, slots_per_epoch: u64) -> Self { + Self { + votes: v28 + .votes_v28 + .into_iter() + .map(|vote| vote.into_v29_with_slots_per_epoch(slots_per_epoch)) + .collect(), + prune_threshold: v28.prune_threshold, + nodes: v28 + .nodes + .into_iter() + .map(|mut node| { + node.best_child = None; + node.best_descendant = None; + ProtoNode::V17(node) + }) + .collect(), + indices: v28.indices, + } + } } impl TryFrom<(SszContainerV29, JustifiedBalances)> for ProtoArrayForkChoice {