diff --git a/Cargo.lock b/Cargo.lock index 0b1d4d205c..aef7995490 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1000,16 +1000,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ctor" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" -dependencies = [ - "quote 1.0.10", - "syn 1.0.81", -] - [[package]] name = "ctrlc" version = "3.2.1" @@ -1332,15 +1322,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "erased-serde" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de9ad4541d99dc22b59134e7ff8dc3d6c988c89ecd7324bf10a8362b07a2afa" -dependencies = [ - "serde", -] - [[package]] name = "errno" version = "0.2.8" @@ -1711,17 +1692,6 @@ dependencies = [ "wasi 0.10.2+wasi-snapshot-preview1", ] -[[package]] -name = "ghost" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" -dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", -] - [[package]] name = "gimli" version = "0.25.0" @@ -2103,16 +2073,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "inventory" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1367fed6750ff2a5bcb967a631528303bb85631f167a75eb1bf7762d57eb7678" -dependencies = [ - "ctor", - "ghost", -] - [[package]] name = "iovec" version = "0.1.4" @@ -6181,7 +6141,6 @@ dependencies = [ "solana-program-runtime", "solana-sdk", "thiserror", - "typetag", ] [[package]] @@ -7125,30 +7084,6 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" -[[package]] -name = "typetag" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4080564c5b2241b5bff53ab610082234e0c57b0417f4bd10596f183001505b8a" -dependencies = [ - "erased-serde", - "inventory", - "once_cell", - "serde", - "typetag-impl", -] - -[[package]] -name = "typetag-impl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60147782cc30833c05fba3bab1d9b5771b2685a2557672ac96fa5d154099c0e" -dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "syn 1.0.81", -] - [[package]] name = "ucd-trie" version = "0.1.3" diff --git a/core/src/cluster_info_vote_listener.rs b/core/src/cluster_info_vote_listener.rs index 124d4a6c5f..a47e3bbd52 100644 --- a/core/src/cluster_info_vote_listener.rs +++ b/core/src/cluster_info_vote_listener.rs @@ -677,7 +677,7 @@ impl ClusterInfoVoteListener { #[allow(clippy::too_many_arguments)] fn track_new_votes_and_notify_confirmations( - vote: Box, + 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, diff --git a/core/src/consensus.rs b/core/src/consensus.rs index dcb5bf2741..b40b4fa3ed 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -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 { - 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 { @@ -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) } diff --git a/core/src/verified_vote_packets.rs b/core/src/verified_vote_packets.rs index e1348ad935..191d23039e 100644 --- a/core/src/verified_vote_packets.rs +++ b/core/src/verified_vote_packets.rs @@ -18,7 +18,7 @@ const MAX_VOTES_PER_VALIDATOR: usize = 1000; pub struct VerifiedVoteMetadata { pub vote_account_key: Pubkey, - pub vote: Box, + 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, diff --git a/programs/bpf/Cargo.lock b/programs/bpf/Cargo.lock index 573370ef74..9a0fc1f1ca 100644 --- a/programs/bpf/Cargo.lock +++ b/programs/bpf/Cargo.lock @@ -600,16 +600,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "ctor" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" -dependencies = [ - "quote 1.0.6", - "syn 1.0.67", -] - [[package]] name = "curve25519-dalek" version = "2.1.0" @@ -880,15 +870,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "erased-serde" -version = "0.3.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3de9ad4541d99dc22b59134e7ff8dc3d6c988c89ecd7324bf10a8362b07a2afa" -dependencies = [ - "serde", -] - [[package]] name = "errno" version = "0.2.8" @@ -1126,17 +1107,6 @@ dependencies = [ "wasi 0.10.1+wasi-snapshot-preview1", ] -[[package]] -name = "ghost" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5bcf1bbeab73aa4cf2fde60a846858dc036163c7c33bec309f8d17de785479" -dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", -] - [[package]] name = "gimli" version = "0.21.0" @@ -1383,16 +1353,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "inventory" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1367fed6750ff2a5bcb967a631528303bb85631f167a75eb1bf7762d57eb7678" -dependencies = [ - "ctor", - "ghost", -] - [[package]] name = "ipnet" version = "2.3.0" @@ -3610,7 +3570,6 @@ dependencies = [ "solana-program-runtime", "solana-sdk", "thiserror", - "typetag", ] [[package]] @@ -4084,30 +4043,6 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" -[[package]] -name = "typetag" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4080564c5b2241b5bff53ab610082234e0c57b0417f4bd10596f183001505b8a" -dependencies = [ - "erased-serde", - "inventory", - "once_cell", - "serde", - "typetag-impl", -] - -[[package]] -name = "typetag-impl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e60147782cc30833c05fba3bab1d9b5771b2685a2557672ac96fa5d154099c0e" -dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.6", - "syn 1.0.67", -] - [[package]] name = "unicode-bidi" version = "0.3.4" diff --git a/programs/vote/Cargo.toml b/programs/vote/Cargo.toml index 8d9011b75d..d85c93ccbf 100644 --- a/programs/vote/Cargo.toml +++ b/programs/vote/Cargo.toml @@ -22,7 +22,6 @@ solana-logger = { path = "../../logger", version = "=1.10.0" } solana-metrics = { path = "../../metrics", version = "=1.10.0" } solana-program-runtime = { path = "../../program-runtime", version = "=1.10.0" } solana-sdk = { path = "../../sdk", version = "=1.10.0" } -typetag = "0.1" thiserror = "1.0" [build-dependencies] diff --git a/programs/vote/src/vote_state/mod.rs b/programs/vote/src/vote_state/mod.rs index 2435cc47fe..db7c623ac0 100644 --- a/programs/vote/src/vote_state/mod.rs +++ b/programs/vote/src/vote_state/mod.rs @@ -19,7 +19,6 @@ use { sysvar::clock::Clock, }, std::{ - any::Any, boxed::Box, cmp::Ordering, collections::{HashSet, VecDeque}, @@ -41,63 +40,70 @@ pub const MAX_EPOCH_CREDITS_HISTORY: usize = 64; // Offset of VoteState::prior_voters, for determining initialization status without deserialization const DEFAULT_PRIOR_VOTERS_OFFSET: usize = 82; -// VoteTransactionClone hack is done so that we can derive clone on the tower that uses the -// VoteTransaction trait object. Clone doesn't work here because it returns Self which is not -// allowed for trait objects -#[typetag::serde{tag = "type"}] -pub trait VoteTransaction: VoteTransactionClone + Debug + Send { - fn slot(&self, i: usize) -> Slot; - fn len(&self) -> usize; - fn hash(&self) -> Hash; - fn timestamp(&self) -> Option; - fn last_voted_slot(&self) -> Option; - fn last_voted_slot_hash(&self) -> Option<(Slot, Hash)>; - fn set_timestamp(&mut self, ts: Option); - - fn slots(&self) -> Vec { - (0..self.len()).map(|i| self.slot(i)).collect() - } - - fn is_empty(&self) -> bool { - self.len() == 0 - } - - // Have to manually implement because deriving PartialEq returns Self - fn eq(&self, other: &dyn VoteTransaction) -> bool; - fn as_any(&self) -> &dyn Any; +#[derive(Debug, PartialEq)] +pub enum VoteTransaction { + Vote(Vote), + VoteStateUpdate(VoteStateUpdate), } -pub trait VoteTransactionClone { - fn clone_box(&self) -> Box; -} +impl VoteTransaction { + pub fn slots(&self) -> Vec { + match self { + VoteTransaction::Vote(vote) => vote.slots.clone(), + VoteTransaction::VoteStateUpdate(vote_state_update) => vote_state_update + .lockouts + .iter() + .map(|lockout| lockout.slot) + .collect(), + } + } -impl VoteTransactionClone for T -where - T: VoteTransaction + Clone + 'static, -{ - fn clone_box(&self) -> Box { - Box::new(self.clone()) + pub fn is_empty(&self) -> bool { + match self { + VoteTransaction::Vote(vote) => vote.slots.is_empty(), + VoteTransaction::VoteStateUpdate(vote_state_update) => { + vote_state_update.lockouts.is_empty() + } + } + } + + pub fn hash(&self) -> Hash { + match self { + VoteTransaction::Vote(vote) => vote.hash, + VoteTransaction::VoteStateUpdate(vote_state_update) => vote_state_update.hash, + } + } + + pub fn timestamp(&self) -> Option { + match self { + VoteTransaction::Vote(vote) => vote.timestamp, + VoteTransaction::VoteStateUpdate(vote_state_update) => vote_state_update.timestamp, + } + } + + pub fn last_voted_slot(&self) -> Option { + match self { + VoteTransaction::Vote(vote) => vote.slots.last().copied(), + VoteTransaction::VoteStateUpdate(vote_state_update) => { + Some(vote_state_update.lockouts.back()?.slot) + } + } + } + + pub fn last_voted_slot_hash(&self) -> Option<(Slot, Hash)> { + Some((self.last_voted_slot()?, self.hash())) } } -impl Clone for Box { - fn clone(&self) -> Box { - self.clone_box() +impl From for VoteTransaction { + fn from(vote: Vote) -> Self { + VoteTransaction::Vote(vote) } } -// Have to manually implement because derive returns Self -impl<'a, 'b> PartialEq for dyn VoteTransaction + 'a { - fn eq(&self, other: &(dyn VoteTransaction + 'b)) -> bool { - VoteTransaction::eq(self, other) - } -} - -// This is needed because of weirdness in the derive PartialEq macro -// See rust issue #31740 for more info -impl PartialEq<&Self> for Box { - fn eq(&self, other: &&Self) -> bool { - VoteTransaction::eq(self.as_ref(), other.as_ref()) +impl From for VoteTransaction { + fn from(vote_state_update: VoteStateUpdate) -> Self { + VoteTransaction::VoteStateUpdate(vote_state_update) } } @@ -122,48 +128,6 @@ impl Vote { } } -#[typetag::serde] -impl VoteTransaction for Vote { - fn slot(&self, i: usize) -> Slot { - self.slots[i] - } - - fn len(&self) -> usize { - self.slots.len() - } - - fn hash(&self) -> Hash { - self.hash - } - - fn timestamp(&self) -> Option { - self.timestamp - } - - fn last_voted_slot(&self) -> Option { - self.slots.last().copied() - } - - fn last_voted_slot_hash(&self) -> Option<(Slot, Hash)> { - self.slots.last().copied().map(|slot| (slot, self.hash)) - } - - fn set_timestamp(&mut self, ts: Option) { - self.timestamp = ts - } - - fn eq(&self, other: &dyn VoteTransaction) -> bool { - other - .as_any() - .downcast_ref::() - .map_or(false, |x| x == self) - } - - fn as_any(&self) -> &dyn Any { - self - } -} - #[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Copy, Clone, AbiExample)] pub struct Lockout { pub slot: Slot, @@ -218,51 +182,6 @@ impl VoteStateUpdate { } } -#[typetag::serde] -impl VoteTransaction for VoteStateUpdate { - fn slot(&self, i: usize) -> Slot { - self.lockouts[i].slot - } - - fn len(&self) -> usize { - self.lockouts.len() - } - - fn hash(&self) -> Hash { - self.hash - } - - fn timestamp(&self) -> Option { - self.timestamp - } - - fn last_voted_slot(&self) -> Option { - self.lockouts.back().copied().map(|lockout| lockout.slot) - } - - fn last_voted_slot_hash(&self) -> Option<(Slot, Hash)> { - self.lockouts - .back() - .copied() - .map(|lockout| (lockout.slot, self.hash)) - } - - fn set_timestamp(&mut self, ts: Option) { - self.timestamp = ts - } - - fn eq(&self, other: &dyn VoteTransaction) -> bool { - other - .as_any() - .downcast_ref::() - .map_or(false, |x| x == self) - } - - fn as_any(&self) -> &dyn Any { - self - } -} - #[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)] pub struct VoteInit { pub node_pubkey: Pubkey, @@ -465,7 +384,7 @@ impl VoteState { fn check_slots_are_valid( &self, - vote: &(impl VoteTransaction + Debug), + vote: &Vote, slot_hashes: &[(Slot, Hash)], ) -> Result<(), VoteError> { // index into the vote's slots, sarting at the newest @@ -484,19 +403,19 @@ impl VoteState { // // 2) Conversely, `slot_hashes` is sorted from newest/largest vote to // the oldest/smallest vote - while i < vote.len() && j > 0 { + while i < vote.slots.len() && j > 0 { // 1) increment `i` to find the smallest slot `s` in `vote.slots` // where `s` >= `last_voted_slot` if self .last_voted_slot() - .map_or(false, |last_voted_slot| vote.slot(i) <= last_voted_slot) + .map_or(false, |last_voted_slot| vote.slots[i] <= last_voted_slot) { i += 1; continue; } // 2) Find the hash for this slot `s`. - if vote.slot(i) != slot_hashes[j - 1].0 { + if vote.slots[i] != slot_hashes[j - 1].0 { // Decrement `j` to find newer slots j -= 1; continue; @@ -518,7 +437,7 @@ impl VoteState { ); return Err(VoteError::VoteTooOld); } - if i != vote.len() { + if i != vote.slots.len() { // This means there existed some slot for which we couldn't find // a matching slot hash in step 2) info!( @@ -528,16 +447,13 @@ impl VoteState { inc_new_counter_info!("dropped-vote-slot", 1); return Err(VoteError::SlotsMismatch); } - if slot_hashes[j].1 != vote.hash() { + if slot_hashes[j].1 != vote.hash { // This means the newest vote in the slot has a match that // doesn't match the expected hash for that slot on this // fork warn!( "{} dropped vote {:?} failed to match hash {} {}", - self.node_pubkey, - vote, - vote.hash(), - slot_hashes[j].1 + self.node_pubkey, vote, vote.hash, slot_hashes[j].1 ); inc_new_counter_info!("dropped-vote-hash", 1); return Err(VoteError::SlotHashMismatch); @@ -1160,8 +1076,18 @@ pub fn process_vote_state_update( signers: &HashSet, ) -> Result<(), InstructionError> { let mut vote_state = verify_and_get_vote_state(vote_account, clock, signers)?; - - vote_state.check_slots_are_valid(&vote_state_update, slot_hashes)?; + { + let vote = Vote { + slots: vote_state_update + .lockouts + .iter() + .map(|lockout| lockout.slot) + .collect(), + hash: vote_state_update.hash, + timestamp: vote_state_update.timestamp, + }; + vote_state.check_slots_are_valid(&vote, slot_hashes)?; + } vote_state.process_new_vote_state( vote_state_update.lockouts, vote_state_update.root, diff --git a/programs/vote/src/vote_transaction.rs b/programs/vote/src/vote_transaction.rs index c421fb5f49..2ff43d4bea 100644 --- a/programs/vote/src/vote_transaction.rs +++ b/programs/vote/src/vote_transaction.rs @@ -14,22 +14,24 @@ use { }, }; -pub type ParsedVote = (Pubkey, Box, Option); +pub type ParsedVote = (Pubkey, VoteTransaction, Option); fn parse_vote(vote_ix: &CompiledInstruction, vote_key: &Pubkey) -> Option { let vote_instruction = limited_deserialize(&vote_ix.data).ok(); vote_instruction.and_then(|vote_instruction| { let result: Option = match vote_instruction { - VoteInstruction::Vote(vote) => Some((*vote_key, Box::new(vote), None)), + VoteInstruction::Vote(vote) => Some((*vote_key, VoteTransaction::from(vote), None)), VoteInstruction::VoteSwitch(vote, hash) => { - Some((*vote_key, Box::new(vote), Some(hash))) + Some((*vote_key, VoteTransaction::from(vote), Some(hash))) } VoteInstruction::UpdateVoteState(vote_state_update) => { - Some((*vote_key, Box::new(vote_state_update), None)) - } - VoteInstruction::UpdateVoteStateSwitch(vote_state_update, hash) => { - Some((*vote_key, Box::new(vote_state_update), Some(hash))) + Some((*vote_key, VoteTransaction::from(vote_state_update), None)) } + VoteInstruction::UpdateVoteStateSwitch(vote_state_update, hash) => Some(( + *vote_key, + VoteTransaction::from(vote_state_update), + Some(hash), + )), VoteInstruction::Authorize(_, _) | VoteInstruction::AuthorizeChecked(_) | VoteInstruction::InitializeAccount(_) @@ -139,10 +141,7 @@ mod test { ); let (key, vote, hash) = parse_vote_transaction(&vote_tx).unwrap(); assert_eq!(hash, input_hash); - assert_eq!( - *vote.as_any().downcast_ref::().unwrap(), - Vote::new(vec![42], bank_hash) - ); + assert_eq!(vote, VoteTransaction::from(Vote::new(vec![42], bank_hash))); assert_eq!(key, vote_keypair.pubkey()); // Test bad program id fails diff --git a/rpc/src/rpc_pubsub.rs b/rpc/src/rpc_pubsub.rs index b9564fb9f1..09e8fbd876 100644 --- a/rpc/src/rpc_pubsub.rs +++ b/rpc/src/rpc_pubsub.rs @@ -611,7 +611,7 @@ mod tests { transaction::{self, Transaction}, }, solana_stake_program::stake_state, - solana_vote_program::vote_state::Vote, + solana_vote_program::vote_state::{Vote, VoteTransaction}, std::{ sync::{ atomic::{AtomicBool, AtomicU64}, @@ -1315,7 +1315,7 @@ mod tests { hash: Hash::default(), timestamp: None, }; - subscriptions.notify_vote(Box::new(vote)); + subscriptions.notify_vote(VoteTransaction::from(vote)); let response = receiver.recv(); assert_eq!( diff --git a/rpc/src/rpc_subscriptions.rs b/rpc/src/rpc_subscriptions.rs index ce2d84b8ff..4ff4668b35 100644 --- a/rpc/src/rpc_subscriptions.rs +++ b/rpc/src/rpc_subscriptions.rs @@ -93,7 +93,7 @@ impl From for TimestampedNotificationEntry { pub enum NotificationEntry { Slot(SlotInfo), SlotUpdate(SlotUpdate), - Vote(Box), + Vote(VoteTransaction), Root(Slot), Bank(CommitmentSlots), Gossip(Slot), @@ -677,8 +677,8 @@ impl RpcSubscriptions { self.enqueue_notification(NotificationEntry::SignaturesReceived(slot_signatures)); } - pub fn notify_vote(&self, vote: Box) { - self.enqueue_notification(NotificationEntry::Vote(vote.clone())); + pub fn notify_vote(&self, vote: VoteTransaction) { + self.enqueue_notification(NotificationEntry::Vote(vote)); } pub fn notify_roots(&self, mut rooted_slots: Vec) {