Skip to content

Commit

Permalink
Add switching vote instruction (solana-labs#10197)
Browse files Browse the repository at this point in the history
* Add switching vote

* Make sure vote size stays under gossip limit

Co-authored-by: Carl <[email protected]>
  • Loading branch information
carllin and carllin authored May 24, 2020
1 parent 8d32441 commit 3aae98c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 2 deletions.
30 changes: 29 additions & 1 deletion core/src/cluster_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2052,10 +2052,11 @@ pub fn stake_weight_peers<S: std::hash::BuildHasher>(
#[cfg(test)]
mod tests {
use super::*;
use crate::crds_value::CrdsValueLabel;
use crate::crds_value::{CrdsValue, CrdsValueLabel, Vote as CrdsVote};
use rayon::prelude::*;
use solana_perf::test_tx::test_tx;
use solana_sdk::signature::{Keypair, Signer};
use solana_vote_program::{vote_instruction, vote_state::Vote};
use std::collections::HashSet;
use std::net::{IpAddr, Ipv4Addr};
use std::sync::Arc;
Expand Down Expand Up @@ -2763,4 +2764,31 @@ mod tests {
assert_eq!(slots, range);
assert!(since.is_some());
}

#[test]
fn test_vote_size() {
let slots = vec![1; 32];
let vote = Vote::new(slots, Hash::default());
let keypair = Arc::new(Keypair::new());

// Create the biggest possible vote transaction
let vote_ix = vote_instruction::vote_switch(
&keypair.pubkey(),
&keypair.pubkey(),
vote,
Hash::default(),
);
let mut vote_tx = Transaction::new_with_payer(&[vote_ix], Some(&keypair.pubkey()));

vote_tx.partial_sign(&[keypair.as_ref()], Hash::default());
vote_tx.partial_sign(&[keypair.as_ref()], Hash::default());

let vote = CrdsVote {
from: keypair.pubkey(),
transaction: vote_tx,
wallclock: 0,
};
let vote = CrdsValue::new_signed(CrdsData::Vote(1, vote), &Keypair::new());
assert!(bincode::serialized_size(&vote).unwrap() <= MAX_PROTOCOL_PAYLOAD_SIZE);
}
}
41 changes: 40 additions & 1 deletion programs/vote/src/vote_instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use serde_derive::{Deserialize, Serialize};
use solana_metrics::inc_new_counter_info;
use solana_sdk::{
account::{get_signers, KeyedAccount},
hash::Hash,
instruction::{AccountMeta, Instruction, InstructionError, WithSigner},
program_utils::{limited_deserialize, next_keyed_account, DecodeError},
pubkey::Pubkey,
Expand Down Expand Up @@ -95,6 +96,15 @@ pub enum VoteInstruction {
/// 1 - New validator identity (node_pubkey)
///
UpdateValidatorIdentity,

/// A Vote instruction with recent votes
/// requires authorized voter signature
///
/// Expects 3 Accounts:
/// 0 - Vote account to vote with
/// 1 - Slot hashes sysvar
/// 2 - Clock sysvar
VoteSwitch(Vote, Hash),
}

fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction {
Expand Down Expand Up @@ -195,6 +205,26 @@ pub fn vote(vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, vote: Vote)
Instruction::new(id(), &VoteInstruction::Vote(vote), account_metas)
}

pub fn vote_switch(
vote_pubkey: &Pubkey,
authorized_voter_pubkey: &Pubkey,
vote: Vote,
proof_hash: Hash,
) -> Instruction {
let account_metas = vec![
AccountMeta::new(*vote_pubkey, false),
AccountMeta::new_readonly(sysvar::slot_hashes::id(), false),
AccountMeta::new_readonly(sysvar::clock::id(), false),
]
.with_signer(authorized_voter_pubkey);

Instruction::new(
id(),
&VoteInstruction::VoteSwitch(vote, proof_hash),
account_metas,
)
}

pub fn withdraw(
vote_pubkey: &Pubkey,
authorized_withdrawer_pubkey: &Pubkey,
Expand Down Expand Up @@ -245,7 +275,7 @@ pub fn process_instruction(
next_keyed_account(keyed_accounts)?.unsigned_key(),
&signers,
),
VoteInstruction::Vote(vote) => {
VoteInstruction::Vote(vote) | VoteInstruction::VoteSwitch(vote, _) => {
inc_new_counter_info!("vote-native", 1);
vote_state::process_vote(
me,
Expand Down Expand Up @@ -328,6 +358,15 @@ mod tests {
)),
Err(InstructionError::InvalidAccountData),
);
assert_eq!(
process_instruction(&vote_switch(
&Pubkey::default(),
&Pubkey::default(),
Vote::default(),
Hash::default(),
)),
Err(InstructionError::InvalidAccountData),
);
assert_eq!(
process_instruction(&authorize(
&Pubkey::default(),
Expand Down

0 comments on commit 3aae98c

Please sign in to comment.