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:
65
Cargo.lock
generated
65
Cargo.lock
generated
@ -1000,16 +1000,6 @@ dependencies = [
|
|||||||
"memchr",
|
"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]]
|
[[package]]
|
||||||
name = "ctrlc"
|
name = "ctrlc"
|
||||||
version = "3.2.1"
|
version = "3.2.1"
|
||||||
@ -1332,15 +1322,6 @@ dependencies = [
|
|||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "erased-serde"
|
|
||||||
version = "0.3.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3de9ad4541d99dc22b59134e7ff8dc3d6c988c89ecd7324bf10a8362b07a2afa"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@ -1711,17 +1692,6 @@ dependencies = [
|
|||||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
"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]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.25.0"
|
version = "0.25.0"
|
||||||
@ -2103,16 +2073,6 @@ dependencies = [
|
|||||||
"cfg-if 1.0.0",
|
"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]]
|
[[package]]
|
||||||
name = "iovec"
|
name = "iovec"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
@ -6181,7 +6141,6 @@ dependencies = [
|
|||||||
"solana-program-runtime",
|
"solana-program-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"typetag",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -7125,30 +7084,6 @@ version = "1.14.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
|
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]]
|
[[package]]
|
||||||
name = "ucd-trie"
|
name = "ucd-trie"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -677,7 +677,7 @@ impl ClusterInfoVoteListener {
|
|||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn track_new_votes_and_notify_confirmations(
|
fn track_new_votes_and_notify_confirmations(
|
||||||
vote: Box<dyn VoteTransaction>,
|
vote: VoteTransaction,
|
||||||
vote_pubkey: &Pubkey,
|
vote_pubkey: &Pubkey,
|
||||||
vote_tracker: &VoteTracker,
|
vote_tracker: &VoteTracker,
|
||||||
root_bank: &Bank,
|
root_bank: &Bank,
|
||||||
@ -792,7 +792,7 @@ impl ClusterInfoVoteListener {
|
|||||||
fn filter_gossip_votes(
|
fn filter_gossip_votes(
|
||||||
vote_tracker: &VoteTracker,
|
vote_tracker: &VoteTracker,
|
||||||
vote_pubkey: &Pubkey,
|
vote_pubkey: &Pubkey,
|
||||||
vote: &dyn VoteTransaction,
|
vote: &VoteTransaction,
|
||||||
gossip_tx: &Transaction,
|
gossip_tx: &Transaction,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if vote.is_empty() {
|
if vote.is_empty() {
|
||||||
@ -842,7 +842,7 @@ impl ClusterInfoVoteListener {
|
|||||||
.filter_map(|gossip_tx| {
|
.filter_map(|gossip_tx| {
|
||||||
vote_transaction::parse_vote_transaction(gossip_tx)
|
vote_transaction::parse_vote_transaction(gossip_tx)
|
||||||
.filter(|(vote_pubkey, vote, _)| {
|
.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))
|
.map(|v| (true, v))
|
||||||
})
|
})
|
||||||
@ -1249,7 +1249,7 @@ mod tests {
|
|||||||
replay_votes_sender
|
replay_votes_sender
|
||||||
.send((
|
.send((
|
||||||
vote_keypair.pubkey(),
|
vote_keypair.pubkey(),
|
||||||
Box::new(replay_vote.clone()),
|
VoteTransaction::from(replay_vote.clone()),
|
||||||
switch_proof_hash,
|
switch_proof_hash,
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -1537,7 +1537,7 @@ mod tests {
|
|||||||
replay_votes_sender
|
replay_votes_sender
|
||||||
.send((
|
.send((
|
||||||
vote_keypair.pubkey(),
|
vote_keypair.pubkey(),
|
||||||
Box::new(Vote::new(vec![vote_slot], Hash::default())),
|
VoteTransaction::from(Vote::new(vec![vote_slot], Hash::default())),
|
||||||
switch_proof_hash,
|
switch_proof_hash,
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -1685,7 +1685,7 @@ mod tests {
|
|||||||
// Add gossip vote for same slot, should not affect outcome
|
// Add gossip vote for same slot, should not affect outcome
|
||||||
vec![(
|
vec![(
|
||||||
validator0_keypairs.vote_keypair.pubkey(),
|
validator0_keypairs.vote_keypair.pubkey(),
|
||||||
Box::new(Vote::new(vec![voted_slot], Hash::default())),
|
VoteTransaction::from(Vote::new(vec![voted_slot], Hash::default())),
|
||||||
None,
|
None,
|
||||||
)],
|
)],
|
||||||
&bank,
|
&bank,
|
||||||
@ -1741,7 +1741,7 @@ mod tests {
|
|||||||
vote_txs,
|
vote_txs,
|
||||||
vec![(
|
vec![(
|
||||||
validator_keypairs[1].vote_keypair.pubkey(),
|
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,
|
None,
|
||||||
)],
|
)],
|
||||||
&new_root_bank,
|
&new_root_bank,
|
||||||
|
@ -21,9 +21,7 @@ use {
|
|||||||
},
|
},
|
||||||
solana_vote_program::{
|
solana_vote_program::{
|
||||||
vote_instruction,
|
vote_instruction,
|
||||||
vote_state::{
|
vote_state::{BlockTimestamp, Lockout, Vote, VoteState, MAX_LOCKOUT_HISTORY},
|
||||||
BlockTimestamp, Lockout, Vote, VoteState, VoteTransaction, MAX_LOCKOUT_HISTORY,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
@ -411,7 +409,8 @@ impl Tower {
|
|||||||
last_voted_slot_in_bank,
|
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;
|
self.last_vote = new_vote;
|
||||||
|
|
||||||
let new_root = self.root();
|
let new_root = self.root();
|
||||||
@ -434,11 +433,11 @@ impl Tower {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_voted_slot(&self) -> Option<Slot> {
|
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)> {
|
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> {
|
pub fn stray_restored_slot(&self) -> Option<Slot> {
|
||||||
@ -1120,10 +1119,10 @@ impl Tower {
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.last_vote.last_voted_slot().unwrap(),
|
self.last_vote.slots.last().unwrap(),
|
||||||
*self.voted_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(())
|
Ok(())
|
||||||
@ -2248,7 +2247,7 @@ pub mod test {
|
|||||||
let mut local = VoteState::default();
|
let mut local = VoteState::default();
|
||||||
let vote = Tower::apply_vote_and_generate_vote_diff(&mut local, 0, Hash::default(), None);
|
let vote = Tower::apply_vote_and_generate_vote_diff(&mut local, 0, Hash::default(), None);
|
||||||
assert_eq!(local.votes.len(), 1);
|
assert_eq!(local.votes.len(), 1);
|
||||||
assert_eq!(vote.slots(), vec![0]);
|
assert_eq!(vote.slots, vec![0]);
|
||||||
assert_eq!(local.tower(), 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.
|
// another vote for slot 0 should return an empty vote as the diff.
|
||||||
let vote =
|
let vote =
|
||||||
Tower::apply_vote_and_generate_vote_diff(&mut local, 0, Hash::default(), Some(0));
|
Tower::apply_vote_and_generate_vote_diff(&mut local, 0, Hash::default(), Some(0));
|
||||||
assert!(vote.is_empty());
|
assert!(vote.slots.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -2274,7 +2273,7 @@ pub mod test {
|
|||||||
assert_eq!(local.votes.len(), 1);
|
assert_eq!(local.votes.len(), 1);
|
||||||
let vote =
|
let vote =
|
||||||
Tower::apply_vote_and_generate_vote_diff(&mut local, 1, Hash::default(), Some(0));
|
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]);
|
assert_eq!(local.tower(), vec![0, 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2294,7 +2293,7 @@ pub mod test {
|
|||||||
// observable in any of the results.
|
// observable in any of the results.
|
||||||
let vote =
|
let vote =
|
||||||
Tower::apply_vote_and_generate_vote_diff(&mut local, 3, Hash::default(), Some(0));
|
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]);
|
assert_eq!(local.tower(), vec![3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2376,7 +2375,7 @@ pub mod test {
|
|||||||
tower.record_vote(i as u64, Hash::default());
|
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)
|
assert_eq!(expected, tower.last_vote)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ const MAX_VOTES_PER_VALIDATOR: usize = 1000;
|
|||||||
|
|
||||||
pub struct VerifiedVoteMetadata {
|
pub struct VerifiedVoteMetadata {
|
||||||
pub vote_account_key: Pubkey,
|
pub vote_account_key: Pubkey,
|
||||||
pub vote: Box<dyn VoteTransaction>,
|
pub vote: VoteTransaction,
|
||||||
pub packet_batch: PacketBatch,
|
pub packet_batch: PacketBatch,
|
||||||
pub signature: Signature,
|
pub signature: Signature,
|
||||||
}
|
}
|
||||||
@ -198,7 +198,7 @@ mod tests {
|
|||||||
let vote = Vote::new(vec![vote_slot], vote_hash);
|
let vote = Vote::new(vec![vote_slot], vote_hash);
|
||||||
s.send(vec![VerifiedVoteMetadata {
|
s.send(vec![VerifiedVoteMetadata {
|
||||||
vote_account_key,
|
vote_account_key,
|
||||||
vote: Box::new(vote.clone()),
|
vote: VoteTransaction::from(vote.clone()),
|
||||||
packet_batch: PacketBatch::default(),
|
packet_batch: PacketBatch::default(),
|
||||||
signature: Signature::new(&[1u8; 64]),
|
signature: Signature::new(&[1u8; 64]),
|
||||||
}])
|
}])
|
||||||
@ -218,7 +218,7 @@ mod tests {
|
|||||||
// Same slot, same hash, should not be inserted
|
// Same slot, same hash, should not be inserted
|
||||||
s.send(vec![VerifiedVoteMetadata {
|
s.send(vec![VerifiedVoteMetadata {
|
||||||
vote_account_key,
|
vote_account_key,
|
||||||
vote: Box::new(vote),
|
vote: VoteTransaction::from(vote),
|
||||||
packet_batch: PacketBatch::default(),
|
packet_batch: PacketBatch::default(),
|
||||||
signature: Signature::new(&[1u8; 64]),
|
signature: Signature::new(&[1u8; 64]),
|
||||||
}])
|
}])
|
||||||
@ -240,7 +240,7 @@ mod tests {
|
|||||||
let vote = Vote::new(vec![vote_slot], new_vote_hash);
|
let vote = Vote::new(vec![vote_slot], new_vote_hash);
|
||||||
s.send(vec![VerifiedVoteMetadata {
|
s.send(vec![VerifiedVoteMetadata {
|
||||||
vote_account_key,
|
vote_account_key,
|
||||||
vote: Box::new(vote),
|
vote: VoteTransaction::from(vote),
|
||||||
packet_batch: PacketBatch::default(),
|
packet_batch: PacketBatch::default(),
|
||||||
signature: Signature::new(&[1u8; 64]),
|
signature: Signature::new(&[1u8; 64]),
|
||||||
}])
|
}])
|
||||||
@ -263,7 +263,7 @@ mod tests {
|
|||||||
let vote = Vote::new(vec![vote_slot], vote_hash);
|
let vote = Vote::new(vec![vote_slot], vote_hash);
|
||||||
s.send(vec![VerifiedVoteMetadata {
|
s.send(vec![VerifiedVoteMetadata {
|
||||||
vote_account_key,
|
vote_account_key,
|
||||||
vote: Box::new(vote),
|
vote: VoteTransaction::from(vote),
|
||||||
packet_batch: PacketBatch::default(),
|
packet_batch: PacketBatch::default(),
|
||||||
signature: Signature::new(&[2u8; 64]),
|
signature: Signature::new(&[2u8; 64]),
|
||||||
}])
|
}])
|
||||||
@ -302,7 +302,7 @@ mod tests {
|
|||||||
let vote = Vote::new(vec![vote_slot], vote_hash);
|
let vote = Vote::new(vec![vote_slot], vote_hash);
|
||||||
s.send(vec![VerifiedVoteMetadata {
|
s.send(vec![VerifiedVoteMetadata {
|
||||||
vote_account_key,
|
vote_account_key,
|
||||||
vote: Box::new(vote),
|
vote: VoteTransaction::from(vote),
|
||||||
packet_batch: PacketBatch::default(),
|
packet_batch: PacketBatch::default(),
|
||||||
signature: Signature::new(&[1u8; 64]),
|
signature: Signature::new(&[1u8; 64]),
|
||||||
}])
|
}])
|
||||||
@ -339,7 +339,7 @@ mod tests {
|
|||||||
let vote = Vote::new(vec![vote_slot], vote_hash);
|
let vote = Vote::new(vec![vote_slot], vote_hash);
|
||||||
s.send(vec![VerifiedVoteMetadata {
|
s.send(vec![VerifiedVoteMetadata {
|
||||||
vote_account_key,
|
vote_account_key,
|
||||||
vote: Box::new(vote),
|
vote: VoteTransaction::from(vote),
|
||||||
packet_batch: PacketBatch::default(),
|
packet_batch: PacketBatch::default(),
|
||||||
signature: Signature::new_unique(),
|
signature: Signature::new_unique(),
|
||||||
}])
|
}])
|
||||||
@ -393,7 +393,7 @@ mod tests {
|
|||||||
let vote = Vote::new(vec![*vote_slot], *vote_hash);
|
let vote = Vote::new(vec![*vote_slot], *vote_hash);
|
||||||
s.send(vec![VerifiedVoteMetadata {
|
s.send(vec![VerifiedVoteMetadata {
|
||||||
vote_account_key,
|
vote_account_key,
|
||||||
vote: Box::new(vote),
|
vote: VoteTransaction::from(vote),
|
||||||
packet_batch: PacketBatch::new(vec![Packet::default(); num_packets]),
|
packet_batch: PacketBatch::new(vec![Packet::default(); num_packets]),
|
||||||
signature: Signature::new_unique(),
|
signature: Signature::new_unique(),
|
||||||
}])
|
}])
|
||||||
@ -457,7 +457,7 @@ mod tests {
|
|||||||
my_leader_bank.slot() + 1,
|
my_leader_bank.slot() + 1,
|
||||||
));
|
));
|
||||||
let vote_account_key = vote_simulator.vote_pubkeys[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 {
|
s.send(vec![VerifiedVoteMetadata {
|
||||||
vote_account_key,
|
vote_account_key,
|
||||||
vote,
|
vote,
|
||||||
|
65
programs/bpf/Cargo.lock
generated
65
programs/bpf/Cargo.lock
generated
@ -600,16 +600,6 @@ dependencies = [
|
|||||||
"subtle",
|
"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]]
|
[[package]]
|
||||||
name = "curve25519-dalek"
|
name = "curve25519-dalek"
|
||||||
version = "2.1.0"
|
version = "2.1.0"
|
||||||
@ -880,15 +870,6 @@ dependencies = [
|
|||||||
"termcolor",
|
"termcolor",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "erased-serde"
|
|
||||||
version = "0.3.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3de9ad4541d99dc22b59134e7ff8dc3d6c988c89ecd7324bf10a8362b07a2afa"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
@ -1126,17 +1107,6 @@ dependencies = [
|
|||||||
"wasi 0.10.1+wasi-snapshot-preview1",
|
"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]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.21.0"
|
version = "0.21.0"
|
||||||
@ -1383,16 +1353,6 @@ dependencies = [
|
|||||||
"cfg-if 1.0.0",
|
"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]]
|
[[package]]
|
||||||
name = "ipnet"
|
name = "ipnet"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@ -3610,7 +3570,6 @@ dependencies = [
|
|||||||
"solana-program-runtime",
|
"solana-program-runtime",
|
||||||
"solana-sdk",
|
"solana-sdk",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"typetag",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4084,30 +4043,6 @@ version = "1.12.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
|
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]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
@ -22,7 +22,6 @@ solana-logger = { path = "../../logger", version = "=1.10.0" }
|
|||||||
solana-metrics = { path = "../../metrics", version = "=1.10.0" }
|
solana-metrics = { path = "../../metrics", version = "=1.10.0" }
|
||||||
solana-program-runtime = { path = "../../program-runtime", version = "=1.10.0" }
|
solana-program-runtime = { path = "../../program-runtime", version = "=1.10.0" }
|
||||||
solana-sdk = { path = "../../sdk", version = "=1.10.0" }
|
solana-sdk = { path = "../../sdk", version = "=1.10.0" }
|
||||||
typetag = "0.1"
|
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
@ -19,7 +19,6 @@ use {
|
|||||||
sysvar::clock::Clock,
|
sysvar::clock::Clock,
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
any::Any,
|
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::{HashSet, VecDeque},
|
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
|
// Offset of VoteState::prior_voters, for determining initialization status without deserialization
|
||||||
const DEFAULT_PRIOR_VOTERS_OFFSET: usize = 82;
|
const DEFAULT_PRIOR_VOTERS_OFFSET: usize = 82;
|
||||||
|
|
||||||
// VoteTransactionClone hack is done so that we can derive clone on the tower that uses the
|
#[derive(Debug, PartialEq)]
|
||||||
// VoteTransaction trait object. Clone doesn't work here because it returns Self which is not
|
pub enum VoteTransaction {
|
||||||
// allowed for trait objects
|
Vote(Vote),
|
||||||
#[typetag::serde{tag = "type"}]
|
VoteStateUpdate(VoteStateUpdate),
|
||||||
pub trait VoteTransaction: VoteTransactionClone + Debug + Send {
|
|
||||||
fn slot(&self, i: usize) -> Slot;
|
|
||||||
fn len(&self) -> usize;
|
|
||||||
fn hash(&self) -> Hash;
|
|
||||||
fn timestamp(&self) -> Option<UnixTimestamp>;
|
|
||||||
fn last_voted_slot(&self) -> Option<Slot>;
|
|
||||||
fn last_voted_slot_hash(&self) -> Option<(Slot, Hash)>;
|
|
||||||
fn set_timestamp(&mut self, ts: Option<UnixTimestamp>);
|
|
||||||
|
|
||||||
fn slots(&self) -> Vec<Slot> {
|
|
||||||
(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VoteTransactionClone {
|
impl VoteTransaction {
|
||||||
fn clone_box(&self) -> Box<dyn VoteTransaction>;
|
pub fn slots(&self) -> Vec<Slot> {
|
||||||
}
|
match self {
|
||||||
|
VoteTransaction::Vote(vote) => vote.slots.clone(),
|
||||||
|
VoteTransaction::VoteStateUpdate(vote_state_update) => vote_state_update
|
||||||
|
.lockouts
|
||||||
|
.iter()
|
||||||
|
.map(|lockout| lockout.slot)
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> VoteTransactionClone for T
|
pub fn is_empty(&self) -> bool {
|
||||||
where
|
match self {
|
||||||
T: VoteTransaction + Clone + 'static,
|
VoteTransaction::Vote(vote) => vote.slots.is_empty(),
|
||||||
{
|
VoteTransaction::VoteStateUpdate(vote_state_update) => {
|
||||||
fn clone_box(&self) -> Box<dyn VoteTransaction> {
|
vote_state_update.lockouts.is_empty()
|
||||||
Box::new(self.clone())
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<UnixTimestamp> {
|
||||||
|
match self {
|
||||||
|
VoteTransaction::Vote(vote) => vote.timestamp,
|
||||||
|
VoteTransaction::VoteStateUpdate(vote_state_update) => vote_state_update.timestamp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn last_voted_slot(&self) -> Option<Slot> {
|
||||||
|
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<dyn VoteTransaction> {
|
impl From<Vote> for VoteTransaction {
|
||||||
fn clone(&self) -> Box<dyn VoteTransaction> {
|
fn from(vote: Vote) -> Self {
|
||||||
self.clone_box()
|
VoteTransaction::Vote(vote)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to manually implement because derive returns Self
|
impl From<VoteStateUpdate> for VoteTransaction {
|
||||||
impl<'a, 'b> PartialEq<dyn VoteTransaction + 'b> for dyn VoteTransaction + 'a {
|
fn from(vote_state_update: VoteStateUpdate) -> Self {
|
||||||
fn eq(&self, other: &(dyn VoteTransaction + 'b)) -> bool {
|
VoteTransaction::VoteStateUpdate(vote_state_update)
|
||||||
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<dyn VoteTransaction> {
|
|
||||||
fn eq(&self, other: &&Self) -> bool {
|
|
||||||
VoteTransaction::eq(self.as_ref(), other.as_ref())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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<UnixTimestamp> {
|
|
||||||
self.timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
fn last_voted_slot(&self) -> Option<Slot> {
|
|
||||||
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<UnixTimestamp>) {
|
|
||||||
self.timestamp = ts
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eq(&self, other: &dyn VoteTransaction) -> bool {
|
|
||||||
other
|
|
||||||
.as_any()
|
|
||||||
.downcast_ref::<Self>()
|
|
||||||
.map_or(false, |x| x == self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Copy, Clone, AbiExample)]
|
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Copy, Clone, AbiExample)]
|
||||||
pub struct Lockout {
|
pub struct Lockout {
|
||||||
pub slot: Slot,
|
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<UnixTimestamp> {
|
|
||||||
self.timestamp
|
|
||||||
}
|
|
||||||
|
|
||||||
fn last_voted_slot(&self) -> Option<Slot> {
|
|
||||||
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<UnixTimestamp>) {
|
|
||||||
self.timestamp = ts
|
|
||||||
}
|
|
||||||
|
|
||||||
fn eq(&self, other: &dyn VoteTransaction) -> bool {
|
|
||||||
other
|
|
||||||
.as_any()
|
|
||||||
.downcast_ref::<Self>()
|
|
||||||
.map_or(false, |x| x == self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub struct VoteInit {
|
pub struct VoteInit {
|
||||||
pub node_pubkey: Pubkey,
|
pub node_pubkey: Pubkey,
|
||||||
@ -465,7 +384,7 @@ impl VoteState {
|
|||||||
|
|
||||||
fn check_slots_are_valid(
|
fn check_slots_are_valid(
|
||||||
&self,
|
&self,
|
||||||
vote: &(impl VoteTransaction + Debug),
|
vote: &Vote,
|
||||||
slot_hashes: &[(Slot, Hash)],
|
slot_hashes: &[(Slot, Hash)],
|
||||||
) -> Result<(), VoteError> {
|
) -> Result<(), VoteError> {
|
||||||
// index into the vote's slots, sarting at the newest
|
// 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
|
// 2) Conversely, `slot_hashes` is sorted from newest/largest vote to
|
||||||
// the oldest/smallest vote
|
// 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`
|
// 1) increment `i` to find the smallest slot `s` in `vote.slots`
|
||||||
// where `s` >= `last_voted_slot`
|
// where `s` >= `last_voted_slot`
|
||||||
if self
|
if self
|
||||||
.last_voted_slot()
|
.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;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Find the hash for this slot `s`.
|
// 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
|
// Decrement `j` to find newer slots
|
||||||
j -= 1;
|
j -= 1;
|
||||||
continue;
|
continue;
|
||||||
@ -518,7 +437,7 @@ impl VoteState {
|
|||||||
);
|
);
|
||||||
return Err(VoteError::VoteTooOld);
|
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
|
// This means there existed some slot for which we couldn't find
|
||||||
// a matching slot hash in step 2)
|
// a matching slot hash in step 2)
|
||||||
info!(
|
info!(
|
||||||
@ -528,16 +447,13 @@ impl VoteState {
|
|||||||
inc_new_counter_info!("dropped-vote-slot", 1);
|
inc_new_counter_info!("dropped-vote-slot", 1);
|
||||||
return Err(VoteError::SlotsMismatch);
|
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
|
// This means the newest vote in the slot has a match that
|
||||||
// doesn't match the expected hash for that slot on this
|
// doesn't match the expected hash for that slot on this
|
||||||
// fork
|
// fork
|
||||||
warn!(
|
warn!(
|
||||||
"{} dropped vote {:?} failed to match hash {} {}",
|
"{} dropped vote {:?} failed to match hash {} {}",
|
||||||
self.node_pubkey,
|
self.node_pubkey, vote, vote.hash, slot_hashes[j].1
|
||||||
vote,
|
|
||||||
vote.hash(),
|
|
||||||
slot_hashes[j].1
|
|
||||||
);
|
);
|
||||||
inc_new_counter_info!("dropped-vote-hash", 1);
|
inc_new_counter_info!("dropped-vote-hash", 1);
|
||||||
return Err(VoteError::SlotHashMismatch);
|
return Err(VoteError::SlotHashMismatch);
|
||||||
@ -1160,8 +1076,18 @@ pub fn process_vote_state_update<S: std::hash::BuildHasher>(
|
|||||||
signers: &HashSet<Pubkey, S>,
|
signers: &HashSet<Pubkey, S>,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let mut vote_state = verify_and_get_vote_state(vote_account, clock, signers)?;
|
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.process_new_vote_state(
|
||||||
vote_state_update.lockouts,
|
vote_state_update.lockouts,
|
||||||
vote_state_update.root,
|
vote_state_update.root,
|
||||||
|
@ -14,22 +14,24 @@ use {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type ParsedVote = (Pubkey, Box<dyn VoteTransaction>, Option<Hash>);
|
pub type ParsedVote = (Pubkey, VoteTransaction, Option<Hash>);
|
||||||
|
|
||||||
fn parse_vote(vote_ix: &CompiledInstruction, vote_key: &Pubkey) -> Option<ParsedVote> {
|
fn parse_vote(vote_ix: &CompiledInstruction, vote_key: &Pubkey) -> Option<ParsedVote> {
|
||||||
let vote_instruction = limited_deserialize(&vote_ix.data).ok();
|
let vote_instruction = limited_deserialize(&vote_ix.data).ok();
|
||||||
vote_instruction.and_then(|vote_instruction| {
|
vote_instruction.and_then(|vote_instruction| {
|
||||||
let result: Option<ParsedVote> = match vote_instruction {
|
let result: Option<ParsedVote> = 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) => {
|
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) => {
|
VoteInstruction::UpdateVoteState(vote_state_update) => {
|
||||||
Some((*vote_key, Box::new(vote_state_update), None))
|
Some((*vote_key, VoteTransaction::from(vote_state_update), None))
|
||||||
}
|
|
||||||
VoteInstruction::UpdateVoteStateSwitch(vote_state_update, hash) => {
|
|
||||||
Some((*vote_key, Box::new(vote_state_update), Some(hash)))
|
|
||||||
}
|
}
|
||||||
|
VoteInstruction::UpdateVoteStateSwitch(vote_state_update, hash) => Some((
|
||||||
|
*vote_key,
|
||||||
|
VoteTransaction::from(vote_state_update),
|
||||||
|
Some(hash),
|
||||||
|
)),
|
||||||
VoteInstruction::Authorize(_, _)
|
VoteInstruction::Authorize(_, _)
|
||||||
| VoteInstruction::AuthorizeChecked(_)
|
| VoteInstruction::AuthorizeChecked(_)
|
||||||
| VoteInstruction::InitializeAccount(_)
|
| VoteInstruction::InitializeAccount(_)
|
||||||
@ -139,10 +141,7 @@ mod test {
|
|||||||
);
|
);
|
||||||
let (key, vote, hash) = parse_vote_transaction(&vote_tx).unwrap();
|
let (key, vote, hash) = parse_vote_transaction(&vote_tx).unwrap();
|
||||||
assert_eq!(hash, input_hash);
|
assert_eq!(hash, input_hash);
|
||||||
assert_eq!(
|
assert_eq!(vote, VoteTransaction::from(Vote::new(vec![42], bank_hash)));
|
||||||
*vote.as_any().downcast_ref::<Vote>().unwrap(),
|
|
||||||
Vote::new(vec![42], bank_hash)
|
|
||||||
);
|
|
||||||
assert_eq!(key, vote_keypair.pubkey());
|
assert_eq!(key, vote_keypair.pubkey());
|
||||||
|
|
||||||
// Test bad program id fails
|
// Test bad program id fails
|
||||||
|
@ -611,7 +611,7 @@ mod tests {
|
|||||||
transaction::{self, Transaction},
|
transaction::{self, Transaction},
|
||||||
},
|
},
|
||||||
solana_stake_program::stake_state,
|
solana_stake_program::stake_state,
|
||||||
solana_vote_program::vote_state::Vote,
|
solana_vote_program::vote_state::{Vote, VoteTransaction},
|
||||||
std::{
|
std::{
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, AtomicU64},
|
atomic::{AtomicBool, AtomicU64},
|
||||||
@ -1315,7 +1315,7 @@ mod tests {
|
|||||||
hash: Hash::default(),
|
hash: Hash::default(),
|
||||||
timestamp: None,
|
timestamp: None,
|
||||||
};
|
};
|
||||||
subscriptions.notify_vote(Box::new(vote));
|
subscriptions.notify_vote(VoteTransaction::from(vote));
|
||||||
|
|
||||||
let response = receiver.recv();
|
let response = receiver.recv();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -93,7 +93,7 @@ impl From<NotificationEntry> for TimestampedNotificationEntry {
|
|||||||
pub enum NotificationEntry {
|
pub enum NotificationEntry {
|
||||||
Slot(SlotInfo),
|
Slot(SlotInfo),
|
||||||
SlotUpdate(SlotUpdate),
|
SlotUpdate(SlotUpdate),
|
||||||
Vote(Box<dyn VoteTransaction>),
|
Vote(VoteTransaction),
|
||||||
Root(Slot),
|
Root(Slot),
|
||||||
Bank(CommitmentSlots),
|
Bank(CommitmentSlots),
|
||||||
Gossip(Slot),
|
Gossip(Slot),
|
||||||
@ -677,8 +677,8 @@ impl RpcSubscriptions {
|
|||||||
self.enqueue_notification(NotificationEntry::SignaturesReceived(slot_signatures));
|
self.enqueue_notification(NotificationEntry::SignaturesReceived(slot_signatures));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn notify_vote(&self, vote: Box<dyn VoteTransaction>) {
|
pub fn notify_vote(&self, vote: VoteTransaction) {
|
||||||
self.enqueue_notification(NotificationEntry::Vote(vote.clone()));
|
self.enqueue_notification(NotificationEntry::Vote(vote));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn notify_roots(&self, mut rooted_slots: Vec<Slot>) {
|
pub fn notify_roots(&self, mut rooted_slots: Vec<Slot>) {
|
||||||
|
Reference in New Issue
Block a user