Add switching vote instruction (#10197)
* Add switching vote * Make sure vote size stays under gossip limit Co-authored-by: Carl <carl@solana.com>
This commit is contained in:
parent
8d32441b96
commit
3aae98c8be
|
@ -2052,10 +2052,11 @@ pub fn stake_weight_peers<S: std::hash::BuildHasher>(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::crds_value::CrdsValueLabel;
|
use crate::crds_value::{CrdsValue, CrdsValueLabel, Vote as CrdsVote};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use solana_perf::test_tx::test_tx;
|
use solana_perf::test_tx::test_tx;
|
||||||
use solana_sdk::signature::{Keypair, Signer};
|
use solana_sdk::signature::{Keypair, Signer};
|
||||||
|
use solana_vote_program::{vote_instruction, vote_state::Vote};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::net::{IpAddr, Ipv4Addr};
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -2763,4 +2764,31 @@ mod tests {
|
||||||
assert_eq!(slots, range);
|
assert_eq!(slots, range);
|
||||||
assert!(since.is_some());
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_metrics::inc_new_counter_info;
|
use solana_metrics::inc_new_counter_info;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{get_signers, KeyedAccount},
|
account::{get_signers, KeyedAccount},
|
||||||
|
hash::Hash,
|
||||||
instruction::{AccountMeta, Instruction, InstructionError, WithSigner},
|
instruction::{AccountMeta, Instruction, InstructionError, WithSigner},
|
||||||
program_utils::{limited_deserialize, next_keyed_account, DecodeError},
|
program_utils::{limited_deserialize, next_keyed_account, DecodeError},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
|
@ -95,6 +96,15 @@ pub enum VoteInstruction {
|
||||||
/// 1 - New validator identity (node_pubkey)
|
/// 1 - New validator identity (node_pubkey)
|
||||||
///
|
///
|
||||||
UpdateValidatorIdentity,
|
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 {
|
fn initialize_account(vote_pubkey: &Pubkey, vote_init: &VoteInit) -> Instruction {
|
||||||
|
@ -195,6 +205,26 @@ pub fn vote(vote_pubkey: &Pubkey, authorized_voter_pubkey: &Pubkey, vote: Vote)
|
||||||
Instruction::new(id(), &VoteInstruction::Vote(vote), account_metas)
|
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(
|
pub fn withdraw(
|
||||||
vote_pubkey: &Pubkey,
|
vote_pubkey: &Pubkey,
|
||||||
authorized_withdrawer_pubkey: &Pubkey,
|
authorized_withdrawer_pubkey: &Pubkey,
|
||||||
|
@ -245,7 +275,7 @@ pub fn process_instruction(
|
||||||
next_keyed_account(keyed_accounts)?.unsigned_key(),
|
next_keyed_account(keyed_accounts)?.unsigned_key(),
|
||||||
&signers,
|
&signers,
|
||||||
),
|
),
|
||||||
VoteInstruction::Vote(vote) => {
|
VoteInstruction::Vote(vote) | VoteInstruction::VoteSwitch(vote, _) => {
|
||||||
inc_new_counter_info!("vote-native", 1);
|
inc_new_counter_info!("vote-native", 1);
|
||||||
vote_state::process_vote(
|
vote_state::process_vote(
|
||||||
me,
|
me,
|
||||||
|
@ -328,6 +358,15 @@ mod tests {
|
||||||
)),
|
)),
|
||||||
Err(InstructionError::InvalidAccountData),
|
Err(InstructionError::InvalidAccountData),
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
process_instruction(&vote_switch(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Pubkey::default(),
|
||||||
|
Vote::default(),
|
||||||
|
Hash::default(),
|
||||||
|
)),
|
||||||
|
Err(InstructionError::InvalidAccountData),
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(&authorize(
|
process_instruction(&authorize(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
|
|
Loading…
Reference in New Issue