Skip to content

Commit b27c80a

Browse files
authored
vote: deprecate unused legacy vote tx plumbing (pyth-network#274)
1 parent 87a0071 commit b27c80a

File tree

4 files changed

+87
-24
lines changed

4 files changed

+87
-24
lines changed

programs/vote/benches/process_vote.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fn create_accounts() -> (Slot, SlotHashes, Vec<TransactionAccount>, Vec<AccountM
4848
);
4949

5050
for next_vote_slot in 0..num_initial_votes {
51-
vote_state.process_next_vote_slot(next_vote_slot, 0, 0);
51+
vote_state.process_next_vote_slot(next_vote_slot, 0, 0, true, true);
5252
}
5353
let mut vote_account_data: Vec<u8> = vec![0; VoteState::size_of()];
5454
let versioned = VoteStateVersions::new_current(vote_state);

programs/vote/src/vote_state/mod.rs

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@ pub fn process_new_vote_state(
612612
let timely_vote_credits = feature_set.map_or(false, |f| {
613613
f.is_active(&feature_set::timely_vote_credits::id())
614614
});
615+
let deprecate_unused_legacy_vote_plumbing = feature_set.map_or(false, |f| {
616+
f.is_active(&feature_set::deprecate_unused_legacy_vote_plumbing::id())
617+
});
615618
let mut earned_credits = if timely_vote_credits { 0_u64 } else { 1_u64 };
616619

617620
if let Some(new_root) = new_root {
@@ -621,7 +624,11 @@ pub fn process_new_vote_state(
621624
if current_vote.slot() <= new_root {
622625
if timely_vote_credits || (current_vote.slot() != new_root) {
623626
earned_credits = earned_credits
624-
.checked_add(vote_state.credits_for_vote_at_index(current_vote_state_index))
627+
.checked_add(vote_state.credits_for_vote_at_index(
628+
current_vote_state_index,
629+
timely_vote_credits,
630+
deprecate_unused_legacy_vote_plumbing,
631+
))
625632
.expect("`earned_credits` does not overflow");
626633
}
627634
current_vote_state_index = current_vote_state_index
@@ -734,11 +741,19 @@ pub fn process_vote_unfiltered(
734741
slot_hashes: &[SlotHash],
735742
epoch: Epoch,
736743
current_slot: Slot,
744+
timely_vote_credits: bool,
745+
deprecate_unused_legacy_vote_plumbing: bool,
737746
) -> Result<(), VoteError> {
738747
check_slots_are_valid(vote_state, vote_slots, &vote.hash, slot_hashes)?;
739-
vote_slots
740-
.iter()
741-
.for_each(|s| vote_state.process_next_vote_slot(*s, epoch, current_slot));
748+
vote_slots.iter().for_each(|s| {
749+
vote_state.process_next_vote_slot(
750+
*s,
751+
epoch,
752+
current_slot,
753+
timely_vote_credits,
754+
deprecate_unused_legacy_vote_plumbing,
755+
)
756+
});
742757
Ok(())
743758
}
744759

@@ -748,6 +763,8 @@ pub fn process_vote(
748763
slot_hashes: &[SlotHash],
749764
epoch: Epoch,
750765
current_slot: Slot,
766+
timely_vote_credits: bool,
767+
deprecate_unused_legacy_vote_plumbing: bool,
751768
) -> Result<(), VoteError> {
752769
if vote.slots.is_empty() {
753770
return Err(VoteError::EmptySlots);
@@ -769,6 +786,8 @@ pub fn process_vote(
769786
slot_hashes,
770787
epoch,
771788
current_slot,
789+
timely_vote_credits,
790+
deprecate_unused_legacy_vote_plumbing,
772791
)
773792
}
774793

@@ -785,6 +804,8 @@ pub fn process_vote_unchecked(vote_state: &mut VoteState, vote: Vote) -> Result<
785804
&slot_hashes,
786805
vote_state.current_epoch(),
787806
0,
807+
true,
808+
true,
788809
)
789810
}
790811

@@ -1067,7 +1088,18 @@ pub fn process_vote_with_account<S: std::hash::BuildHasher>(
10671088
) -> Result<(), InstructionError> {
10681089
let mut vote_state = verify_and_get_vote_state(vote_account, clock, signers)?;
10691090

1070-
process_vote(&mut vote_state, vote, slot_hashes, clock.epoch, clock.slot)?;
1091+
let timely_vote_credits = feature_set.is_active(&feature_set::timely_vote_credits::id());
1092+
let deprecate_unused_legacy_vote_plumbing =
1093+
feature_set.is_active(&feature_set::deprecate_unused_legacy_vote_plumbing::id());
1094+
process_vote(
1095+
&mut vote_state,
1096+
vote,
1097+
slot_hashes,
1098+
clock.epoch,
1099+
clock.slot,
1100+
timely_vote_credits,
1101+
deprecate_unused_legacy_vote_plumbing,
1102+
)?;
10711103
if let Some(timestamp) = vote.timestamp {
10721104
vote.slots
10731105
.iter()
@@ -1250,7 +1282,7 @@ mod tests {
12501282
134, 135,
12511283
]
12521284
.into_iter()
1253-
.for_each(|v| vote_state.process_next_vote_slot(v, 4, 0));
1285+
.for_each(|v| vote_state.process_next_vote_slot(v, 4, 0, false, true));
12541286

12551287
let version1_14_11_serialized = bincode::serialize(&VoteStateVersions::V1_14_11(Box::new(
12561288
VoteState1_14_11::from(vote_state.clone()),
@@ -1732,11 +1764,11 @@ mod tests {
17321764
let slot_hashes: Vec<_> = vote.slots.iter().rev().map(|x| (*x, vote.hash)).collect();
17331765

17341766
assert_eq!(
1735-
process_vote(&mut vote_state_a, &vote, &slot_hashes, 0, 0),
1767+
process_vote(&mut vote_state_a, &vote, &slot_hashes, 0, 0, true, true),
17361768
Ok(())
17371769
);
17381770
assert_eq!(
1739-
process_vote(&mut vote_state_b, &vote, &slot_hashes, 0, 0),
1771+
process_vote(&mut vote_state_b, &vote, &slot_hashes, 0, 0, true, true),
17401772
Ok(())
17411773
);
17421774
assert_eq!(recent_votes(&vote_state_a), recent_votes(&vote_state_b));
@@ -1749,12 +1781,12 @@ mod tests {
17491781
let vote = Vote::new(vec![0], Hash::default());
17501782
let slot_hashes: Vec<_> = vec![(0, vote.hash)];
17511783
assert_eq!(
1752-
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0),
1784+
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0, true, true),
17531785
Ok(())
17541786
);
17551787
let recent = recent_votes(&vote_state);
17561788
assert_eq!(
1757-
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0),
1789+
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0, true, true),
17581790
Err(VoteError::VoteTooOld)
17591791
);
17601792
assert_eq!(recent, recent_votes(&vote_state));
@@ -1814,7 +1846,7 @@ mod tests {
18141846
let vote = Vote::new(vec![0], Hash::default());
18151847
let slot_hashes: Vec<_> = vec![(*vote.slots.last().unwrap(), vote.hash)];
18161848
assert_eq!(
1817-
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0),
1849+
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0, true, true),
18181850
Ok(())
18191851
);
18201852
assert_eq!(
@@ -1830,7 +1862,7 @@ mod tests {
18301862
let vote = Vote::new(vec![0], Hash::default());
18311863
let slot_hashes: Vec<_> = vec![(*vote.slots.last().unwrap(), vote.hash)];
18321864
assert_eq!(
1833-
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0),
1865+
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0, true, true),
18341866
Ok(())
18351867
);
18361868

@@ -1849,7 +1881,7 @@ mod tests {
18491881
let vote = Vote::new(vec![0], Hash::default());
18501882
let slot_hashes: Vec<_> = vec![(*vote.slots.last().unwrap(), vote.hash)];
18511883
assert_eq!(
1852-
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0),
1884+
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0, true, true),
18531885
Ok(())
18541886
);
18551887

@@ -1866,7 +1898,7 @@ mod tests {
18661898

18671899
let vote = Vote::new(vec![], Hash::default());
18681900
assert_eq!(
1869-
process_vote(&mut vote_state, &vote, &[], 0, 0),
1901+
process_vote(&mut vote_state, &vote, &[], 0, 0, true, true),
18701902
Err(VoteError::EmptySlots)
18711903
);
18721904
}
@@ -2163,7 +2195,9 @@ mod tests {
21632195
&vote,
21642196
&slot_hashes,
21652197
0,
2166-
vote_group.1 // vote_group.1 is the slot in which the vote was cast
2198+
vote_group.1, // vote_group.1 is the slot in which the vote was cast
2199+
true,
2200+
true
21672201
),
21682202
Ok(())
21692203
);
@@ -3055,7 +3089,7 @@ mod tests {
30553089
// error with `VotesTooOldAllFiltered`
30563090
let slot_hashes = vec![(3, Hash::new_unique()), (2, Hash::new_unique())];
30573091
assert_eq!(
3058-
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0),
3092+
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0, true, true),
30593093
Err(VoteError::VotesTooOldAllFiltered)
30603094
);
30613095

@@ -3069,7 +3103,7 @@ mod tests {
30693103
.1;
30703104

30713105
let vote = Vote::new(vec![old_vote_slot, vote_slot], vote_slot_hash);
3072-
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0).unwrap();
3106+
process_vote(&mut vote_state, &vote, &slot_hashes, 0, 0, true, true).unwrap();
30733107
assert_eq!(
30743108
vote_state
30753109
.votes
@@ -3098,8 +3132,17 @@ mod tests {
30983132
.unwrap()
30993133
.1;
31003134
let vote = Vote::new(vote_slots, vote_hash);
3101-
process_vote_unfiltered(&mut vote_state, &vote.slots, &vote, slot_hashes, 0, 0)
3102-
.unwrap();
3135+
process_vote_unfiltered(
3136+
&mut vote_state,
3137+
&vote.slots,
3138+
&vote,
3139+
slot_hashes,
3140+
0,
3141+
0,
3142+
true,
3143+
true,
3144+
)
3145+
.unwrap();
31033146
}
31043147

31053148
vote_state

sdk/program/src/vote/state/mod.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,8 @@ impl VoteState {
514514
next_vote_slot: Slot,
515515
epoch: Epoch,
516516
current_slot: Slot,
517+
timely_vote_credits: bool,
518+
deprecate_unused_legacy_vote_plumbing: bool,
517519
) {
518520
// Ignore votes for slots earlier than we already have votes for
519521
if self
@@ -526,13 +528,21 @@ impl VoteState {
526528
self.pop_expired_votes(next_vote_slot);
527529

528530
let landed_vote = LandedVote {
529-
latency: Self::compute_vote_latency(next_vote_slot, current_slot),
531+
latency: if timely_vote_credits || !deprecate_unused_legacy_vote_plumbing {
532+
Self::compute_vote_latency(next_vote_slot, current_slot)
533+
} else {
534+
0
535+
},
530536
lockout: Lockout::new(next_vote_slot),
531537
};
532538

533539
// Once the stack is full, pop the oldest lockout and distribute rewards
534540
if self.votes.len() == MAX_LOCKOUT_HISTORY {
535-
let credits = self.credits_for_vote_at_index(0);
541+
let credits = self.credits_for_vote_at_index(
542+
0,
543+
timely_vote_credits,
544+
deprecate_unused_legacy_vote_plumbing,
545+
);
536546
let landed_vote = self.votes.pop_front().unwrap();
537547
self.root_slot = Some(landed_vote.slot());
538548

@@ -577,15 +587,20 @@ impl VoteState {
577587
}
578588

579589
/// Returns the credits to award for a vote at the given lockout slot index
580-
pub fn credits_for_vote_at_index(&self, index: usize) -> u64 {
590+
pub fn credits_for_vote_at_index(
591+
&self,
592+
index: usize,
593+
timely_vote_credits: bool,
594+
deprecate_unused_legacy_vote_plumbing: bool,
595+
) -> u64 {
581596
let latency = self
582597
.votes
583598
.get(index)
584599
.map_or(0, |landed_vote| landed_vote.latency);
585600

586601
// If latency is 0, this means that the Lockout was created and stored from a software version that did not
587602
// store vote latencies; in this case, 1 credit is awarded
588-
if latency == 0 {
603+
if latency == 0 || (deprecate_unused_legacy_vote_plumbing && !timely_vote_credits) {
589604
1
590605
} else {
591606
match latency.checked_sub(VOTE_CREDITS_GRACE_SLOTS) {

sdk/src/feature_set.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,10 @@ pub mod remove_rounding_in_fee_calculation {
780780
solana_sdk::declare_id!("BtVN7YjDzNE6Dk7kTT7YTDgMNUZTNgiSJgsdzAeTg2jF");
781781
}
782782

783+
pub mod deprecate_unused_legacy_vote_plumbing {
784+
solana_sdk::declare_id!("6Uf8S75PVh91MYgPQSHnjRAPQq6an5BDv9vomrCwDqLe");
785+
}
786+
783787
lazy_static! {
784788
/// Map of feature identifiers to user-visible description
785789
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
@@ -970,6 +974,7 @@ lazy_static! {
970974
(enable_gossip_duplicate_proof_ingestion::id(), "enable gossip duplicate proof ingestion #32963"),
971975
(enable_chained_merkle_shreds::id(), "Enable chained Merkle shreds #34916"),
972976
(remove_rounding_in_fee_calculation::id(), "Removing unwanted rounding in fee calculation #34982"),
977+
(deprecate_unused_legacy_vote_plumbing::id(), "Deprecate unused legacy vote tx plumbing"),
973978
/*************** ADD NEW FEATURES HERE ***************/
974979
]
975980
.iter()

0 commit comments

Comments
 (0)