uses enum instead of trait for VoteTransaction (#22019)

Box<dyn Trait> involves runtime dispatch, has significant overhead and
is slow. It also requires hacky boilerplate code for implementing Clone
or other basic traits:
https://github.com/solana-labs/solana/blob/e92a81b74/programs/vote/src/vote_state/mod.rs#L70-L102

Only limited known types can be VoteTransaction and they are all defined
in the same crate. So using a trait here only adds overhead.
https://github.com/solana-labs/solana/blob/e92a81b74/programs/vote/src/vote_state/mod.rs#L125-L165
https://github.com/solana-labs/solana/blob/e92a81b74/programs/vote/src/vote_state/mod.rs#L221-L264
This commit is contained in:
behzad nouri
2021-12-22 14:25:46 +00:00
committed by GitHub
parent d6de4a2f4e
commit 4d62f03297
10 changed files with 118 additions and 325 deletions

View File

@ -677,7 +677,7 @@ impl ClusterInfoVoteListener {
#[allow(clippy::too_many_arguments)]
fn track_new_votes_and_notify_confirmations(
vote: Box<dyn VoteTransaction>,
vote: VoteTransaction,
vote_pubkey: &Pubkey,
vote_tracker: &VoteTracker,
root_bank: &Bank,
@ -792,7 +792,7 @@ impl ClusterInfoVoteListener {
fn filter_gossip_votes(
vote_tracker: &VoteTracker,
vote_pubkey: &Pubkey,
vote: &dyn VoteTransaction,
vote: &VoteTransaction,
gossip_tx: &Transaction,
) -> bool {
if vote.is_empty() {
@ -842,7 +842,7 @@ impl ClusterInfoVoteListener {
.filter_map(|gossip_tx| {
vote_transaction::parse_vote_transaction(gossip_tx)
.filter(|(vote_pubkey, vote, _)| {
Self::filter_gossip_votes(vote_tracker, vote_pubkey, &**vote, gossip_tx)
Self::filter_gossip_votes(vote_tracker, vote_pubkey, vote, gossip_tx)
})
.map(|v| (true, v))
})
@ -1249,7 +1249,7 @@ mod tests {
replay_votes_sender
.send((
vote_keypair.pubkey(),
Box::new(replay_vote.clone()),
VoteTransaction::from(replay_vote.clone()),
switch_proof_hash,
))
.unwrap();
@ -1537,7 +1537,7 @@ mod tests {
replay_votes_sender
.send((
vote_keypair.pubkey(),
Box::new(Vote::new(vec![vote_slot], Hash::default())),
VoteTransaction::from(Vote::new(vec![vote_slot], Hash::default())),
switch_proof_hash,
))
.unwrap();
@ -1685,7 +1685,7 @@ mod tests {
// Add gossip vote for same slot, should not affect outcome
vec![(
validator0_keypairs.vote_keypair.pubkey(),
Box::new(Vote::new(vec![voted_slot], Hash::default())),
VoteTransaction::from(Vote::new(vec![voted_slot], Hash::default())),
None,
)],
&bank,
@ -1741,7 +1741,7 @@ mod tests {
vote_txs,
vec![(
validator_keypairs[1].vote_keypair.pubkey(),
Box::new(Vote::new(vec![first_slot_in_new_epoch], Hash::default())),
VoteTransaction::from(Vote::new(vec![first_slot_in_new_epoch], Hash::default())),
None,
)],
&new_root_bank,

View File

@ -21,9 +21,7 @@ use {
},
solana_vote_program::{
vote_instruction,
vote_state::{
BlockTimestamp, Lockout, Vote, VoteState, VoteTransaction, MAX_LOCKOUT_HISTORY,
},
vote_state::{BlockTimestamp, Lockout, Vote, VoteState, MAX_LOCKOUT_HISTORY},
},
std::{
cmp::Ordering,
@ -411,7 +409,8 @@ impl Tower {
last_voted_slot_in_bank,
);
new_vote.set_timestamp(self.maybe_timestamp(self.last_vote.last_voted_slot().unwrap_or(0)));
new_vote.timestamp =
self.maybe_timestamp(self.last_vote.slots.last().copied().unwrap_or_default());
self.last_vote = new_vote;
let new_root = self.root();
@ -434,11 +433,11 @@ impl Tower {
}
pub fn last_voted_slot(&self) -> Option<Slot> {
self.last_vote.last_voted_slot()
self.last_vote.slots.last().copied()
}
pub fn last_voted_slot_hash(&self) -> Option<(Slot, Hash)> {
self.last_vote.last_voted_slot_hash()
Some((*self.last_vote.slots.last()?, self.last_vote.hash))
}
pub fn stray_restored_slot(&self) -> Option<Slot> {
@ -1120,10 +1119,10 @@ impl Tower {
);
assert_eq!(
self.last_vote.last_voted_slot().unwrap(),
*self.voted_slots().last().unwrap()
self.last_vote.slots.last().unwrap(),
self.voted_slots().last().unwrap()
);
self.stray_restored_slot = Some(self.last_vote.last_voted_slot().unwrap());
self.stray_restored_slot = Some(*self.last_vote.slots.last().unwrap());
}
Ok(())
@ -2248,7 +2247,7 @@ pub mod test {
let mut local = VoteState::default();
let vote = Tower::apply_vote_and_generate_vote_diff(&mut local, 0, Hash::default(), None);
assert_eq!(local.votes.len(), 1);
assert_eq!(vote.slots(), vec![0]);
assert_eq!(vote.slots, vec![0]);
assert_eq!(local.tower(), vec![0]);
}
@ -2259,7 +2258,7 @@ pub mod test {
// another vote for slot 0 should return an empty vote as the diff.
let vote =
Tower::apply_vote_and_generate_vote_diff(&mut local, 0, Hash::default(), Some(0));
assert!(vote.is_empty());
assert!(vote.slots.is_empty());
}
#[test]
@ -2274,7 +2273,7 @@ pub mod test {
assert_eq!(local.votes.len(), 1);
let vote =
Tower::apply_vote_and_generate_vote_diff(&mut local, 1, Hash::default(), Some(0));
assert_eq!(vote.slots(), vec![1]);
assert_eq!(vote.slots, vec![1]);
assert_eq!(local.tower(), vec![0, 1]);
}
@ -2294,7 +2293,7 @@ pub mod test {
// observable in any of the results.
let vote =
Tower::apply_vote_and_generate_vote_diff(&mut local, 3, Hash::default(), Some(0));
assert_eq!(vote.slots(), vec![3]);
assert_eq!(vote.slots, vec![3]);
assert_eq!(local.tower(), vec![3]);
}
@ -2376,7 +2375,7 @@ pub mod test {
tower.record_vote(i as u64, Hash::default());
}
expected.timestamp = tower.last_vote.timestamp();
expected.timestamp = tower.last_vote.timestamp;
assert_eq!(expected, tower.last_vote)
}

View File

@ -18,7 +18,7 @@ const MAX_VOTES_PER_VALIDATOR: usize = 1000;
pub struct VerifiedVoteMetadata {
pub vote_account_key: Pubkey,
pub vote: Box<dyn VoteTransaction>,
pub vote: VoteTransaction,
pub packet_batch: PacketBatch,
pub signature: Signature,
}
@ -198,7 +198,7 @@ mod tests {
let vote = Vote::new(vec![vote_slot], vote_hash);
s.send(vec![VerifiedVoteMetadata {
vote_account_key,
vote: Box::new(vote.clone()),
vote: VoteTransaction::from(vote.clone()),
packet_batch: PacketBatch::default(),
signature: Signature::new(&[1u8; 64]),
}])
@ -218,7 +218,7 @@ mod tests {
// Same slot, same hash, should not be inserted
s.send(vec![VerifiedVoteMetadata {
vote_account_key,
vote: Box::new(vote),
vote: VoteTransaction::from(vote),
packet_batch: PacketBatch::default(),
signature: Signature::new(&[1u8; 64]),
}])
@ -240,7 +240,7 @@ mod tests {
let vote = Vote::new(vec![vote_slot], new_vote_hash);
s.send(vec![VerifiedVoteMetadata {
vote_account_key,
vote: Box::new(vote),
vote: VoteTransaction::from(vote),
packet_batch: PacketBatch::default(),
signature: Signature::new(&[1u8; 64]),
}])
@ -263,7 +263,7 @@ mod tests {
let vote = Vote::new(vec![vote_slot], vote_hash);
s.send(vec![VerifiedVoteMetadata {
vote_account_key,
vote: Box::new(vote),
vote: VoteTransaction::from(vote),
packet_batch: PacketBatch::default(),
signature: Signature::new(&[2u8; 64]),
}])
@ -302,7 +302,7 @@ mod tests {
let vote = Vote::new(vec![vote_slot], vote_hash);
s.send(vec![VerifiedVoteMetadata {
vote_account_key,
vote: Box::new(vote),
vote: VoteTransaction::from(vote),
packet_batch: PacketBatch::default(),
signature: Signature::new(&[1u8; 64]),
}])
@ -339,7 +339,7 @@ mod tests {
let vote = Vote::new(vec![vote_slot], vote_hash);
s.send(vec![VerifiedVoteMetadata {
vote_account_key,
vote: Box::new(vote),
vote: VoteTransaction::from(vote),
packet_batch: PacketBatch::default(),
signature: Signature::new_unique(),
}])
@ -393,7 +393,7 @@ mod tests {
let vote = Vote::new(vec![*vote_slot], *vote_hash);
s.send(vec![VerifiedVoteMetadata {
vote_account_key,
vote: Box::new(vote),
vote: VoteTransaction::from(vote),
packet_batch: PacketBatch::new(vec![Packet::default(); num_packets]),
signature: Signature::new_unique(),
}])
@ -457,7 +457,7 @@ mod tests {
my_leader_bank.slot() + 1,
));
let vote_account_key = vote_simulator.vote_pubkeys[1];
let vote = Box::new(Vote::new(vec![vote_slot], vote_hash));
let vote = VoteTransaction::from(Vote::new(vec![vote_slot], vote_hash));
s.send(vec![VerifiedVoteMetadata {
vote_account_key,
vote,