From 9c07a8c26aa92e6d4d1a8f91114e6ee688dfd50d Mon Sep 17 00:00:00 2001 From: Greg Fitzgerald Date: Fri, 1 Feb 2019 15:50:11 -0700 Subject: [PATCH] VoteProgram -> VoteState --- fullnode/src/main.rs | 4 +- programs/native/vote/src/lib.rs | 82 ++++++++++------------ sdk/src/vote_program.rs | 18 ++--- sdk/src/vote_transaction.rs | 27 ++++--- src/compute_leader_confirmation_service.rs | 6 +- src/leader_scheduler.rs | 4 +- src/thin_client.rs | 4 +- 7 files changed, 67 insertions(+), 78 deletions(-) diff --git a/fullnode/src/main.rs b/fullnode/src/main.rs index 111d6f5f65..64a1867bf9 100644 --- a/fullnode/src/main.rs +++ b/fullnode/src/main.rs @@ -10,7 +10,7 @@ use solana::thin_client::{poll_gossip_for_leader, ThinClient}; use solana::voting_keypair::{RemoteVoteSigner, VotingKeypair}; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::vote_program::VoteProgram; +use solana_sdk::vote_program::VoteState; use solana_sdk::vote_transaction::VoteTransaction; use solana_vote_signer::rpc::{LocalVoteSigner, VoteSigner}; use std::fs::File; @@ -112,7 +112,7 @@ fn create_and_fund_vote_account( info!("Checking for vote account registration"); let vote_account_user_data = client.get_account_userdata(&vote_account); if let Ok(Some(vote_account_user_data)) = vote_account_user_data { - if let Ok(vote_state) = VoteProgram::deserialize(&vote_account_user_data) { + if let Ok(vote_state) = VoteState::deserialize(&vote_account_user_data) { if vote_state.node_id == pubkey { return Ok(()); } diff --git a/programs/native/vote/src/lib.rs b/programs/native/vote/src/lib.rs index 65bb36f109..8847c8d7b2 100644 --- a/programs/native/vote/src/lib.rs +++ b/programs/native/vote/src/lib.rs @@ -7,7 +7,7 @@ use solana_sdk::account::KeyedAccount; use solana_sdk::native_program::ProgramError; use solana_sdk::pubkey::Pubkey; use solana_sdk::solana_entrypoint; -use solana_sdk::vote_program::{self, Vote, VoteInstruction, VoteProgram}; +use solana_sdk::vote_program::{self, Vote, VoteInstruction, VoteState}; fn register(keyed_accounts: &mut [KeyedAccount]) -> Result<(), ProgramError> { if !vote_program::check_id(&keyed_accounts[1].account.owner) { @@ -15,9 +15,7 @@ fn register(keyed_accounts: &mut [KeyedAccount]) -> Result<(), ProgramError> { Err(ProgramError::InvalidArgument)?; } - // TODO: a single validator could register multiple "vote accounts" - // which would clutter the "accounts" structure. See github issue 1654. - let vote_state = VoteProgram::new(*keyed_accounts[0].signer_key().unwrap()); + let vote_state = VoteState::new(*keyed_accounts[0].signer_key().unwrap()); vote_state.serialize(&mut keyed_accounts[1].account.userdata)?; Ok(()) @@ -29,7 +27,7 @@ fn process_vote(keyed_accounts: &mut [KeyedAccount], vote: Vote) -> Result<(), P Err(ProgramError::InvalidArgument)?; } - let mut vote_state = VoteProgram::deserialize(&keyed_accounts[0].account.userdata)?; + let mut vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata)?; // TODO: Integrity checks // a) Verify the vote's bank hash matches what is expected @@ -66,7 +64,7 @@ fn entrypoint( match deserialize(data).map_err(|_| ProgramError::InvalidUserdata)? { VoteInstruction::RegisterAccount => register(keyed_accounts), - VoteInstruction::NewVote(vote) => { + VoteInstruction::Vote(vote) => { debug!("{:?} by {}", vote, keyed_accounts[0].signer_key().unwrap()); solana_metrics::submit( solana_metrics::influxdb::Point::new("vote-native") @@ -85,85 +83,79 @@ mod tests { use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::vote_program; - fn create_vote_program(tokens: u64) -> Account { + fn create_vote_account(tokens: u64) -> Account { let space = vote_program::get_max_size(); Account::new(tokens, space, vote_program::id()) } fn register_and_deserialize( - voter_id: &Pubkey, - voter_account: &mut Account, - vote_state_id: &Pubkey, - vote_state_account: &mut Account, - ) -> Result { + from_id: &Pubkey, + from_account: &mut Account, + vote_id: &Pubkey, + vote_account: &mut Account, + ) -> Result { let mut keyed_accounts = [ - KeyedAccount::new(voter_id, true, voter_account), - KeyedAccount::new(vote_state_id, false, vote_state_account), + KeyedAccount::new(from_id, true, from_account), + KeyedAccount::new(vote_id, false, vote_account), ]; register(&mut keyed_accounts)?; - let vote_state = VoteProgram::deserialize(&vote_state_account.userdata).unwrap(); + let vote_state = VoteState::deserialize(&vote_account.userdata).unwrap(); Ok(vote_state) } fn vote_and_deserialize( - vote_state_id: &Pubkey, - vote_state_account: &mut Account, + vote_id: &Pubkey, + vote_account: &mut Account, vote: Vote, - ) -> Result { - let mut keyed_accounts = [KeyedAccount::new(vote_state_id, true, vote_state_account)]; + ) -> Result { + let mut keyed_accounts = [KeyedAccount::new(vote_id, true, vote_account)]; process_vote(&mut keyed_accounts, vote)?; - let vote_state = VoteProgram::deserialize(&vote_state_account.userdata).unwrap(); + let vote_state = VoteState::deserialize(&vote_account.userdata).unwrap(); Ok(vote_state) } #[test] fn test_voter_registration() { - let voter_id = Keypair::new().pubkey(); - let mut voter_account = Account::new(100, 0, Pubkey::default()); + let from_id = Keypair::new().pubkey(); + let mut from_account = Account::new(100, 0, Pubkey::default()); - let vote_state_id = Keypair::new().pubkey(); - let mut vote_state_account = create_vote_program(100); + let vote_id = Keypair::new().pubkey(); + let mut vote_account = create_vote_account(100); - let vote_state = register_and_deserialize( - &voter_id, - &mut voter_account, - &vote_state_id, - &mut vote_state_account, - ) - .unwrap(); - assert_eq!(vote_state.node_id, voter_id); + let vote_state = + register_and_deserialize(&from_id, &mut from_account, &vote_id, &mut vote_account) + .unwrap(); + assert_eq!(vote_state.node_id, from_id); assert!(vote_state.votes.is_empty()); } #[test] fn test_vote() { - let voter_id = Keypair::new().pubkey(); - let mut voter_account = Account::new(100, 0, Pubkey::default()); + let from_id = Keypair::new().pubkey(); + let mut from_account = Account::new(100, 0, Pubkey::default()); - let vote_state_id = Keypair::new().pubkey(); - let mut vote_state_account = create_vote_program(100); + let vote_id = Keypair::new().pubkey(); + let mut vote_account = create_vote_account(100); let mut keyed_accounts = [ - KeyedAccount::new(&voter_id, true, &mut voter_account), - KeyedAccount::new(&vote_state_id, false, &mut vote_state_account), + KeyedAccount::new(&from_id, true, &mut from_account), + KeyedAccount::new(&vote_id, false, &mut vote_account), ]; register(&mut keyed_accounts).unwrap(); let vote = Vote::new(1); - let vote_state = - vote_and_deserialize(&vote_state_id, &mut vote_state_account, vote.clone()).unwrap(); + let vote_state = vote_and_deserialize(&vote_id, &mut vote_account, vote.clone()).unwrap(); assert_eq!(vote_state.votes, vec![vote]); } #[test] - // TODO: Should this work? fn test_vote_without_registration() { - let vote_state_id = Keypair::new().pubkey(); - let mut vote_state_account = create_vote_program(100); + let vote_id = Keypair::new().pubkey(); + let mut vote_account = create_vote_account(100); let vote = Vote::new(1); - let vote_state = - vote_and_deserialize(&vote_state_id, &mut vote_state_account, vote.clone()).unwrap(); + let vote_state = vote_and_deserialize(&vote_id, &mut vote_account, vote.clone()).unwrap(); + assert_eq!(vote_state.node_id, Pubkey::default()); assert_eq!(vote_state.votes, vec![vote]); } } diff --git a/sdk/src/vote_program.rs b/sdk/src/vote_program.rs index fc620ac935..ef644f8560 100644 --- a/sdk/src/vote_program.rs +++ b/sdk/src/vote_program.rs @@ -43,34 +43,34 @@ pub enum VoteInstruction { /// * Transaction::keys[1] - the new "vote account" to be associated with the validator /// identified by keys[0] for voting RegisterAccount, - NewVote(Vote), + Vote(Vote), } #[derive(Debug, Default, Serialize, Deserialize, PartialEq, Eq)] -pub struct VoteProgram { +pub struct VoteState { pub votes: VecDeque, pub node_id: Pubkey, } pub fn get_max_size() -> usize { // Upper limit on the size of the Vote State. Equal to - // sizeof(VoteProgram) when votes.len() is MAX_VOTE_HISTORY - let mut vote_program = VoteProgram::default(); + // sizeof(VoteState) when votes.len() is MAX_VOTE_HISTORY + let mut vote_program = VoteState::default(); vote_program.votes = VecDeque::from(vec![Vote::default(); MAX_VOTE_HISTORY]); serialized_size(&vote_program).unwrap() as usize } -impl VoteProgram { +impl VoteState { pub fn new(node_id: Pubkey) -> Self { let votes = VecDeque::new(); Self { votes, node_id } } - pub fn deserialize(input: &[u8]) -> Result { + pub fn deserialize(input: &[u8]) -> Result { deserialize(input).map_err(|_| ProgramError::InvalidUserdata) } - pub fn serialize(self: &VoteProgram, output: &mut [u8]) -> Result<(), ProgramError> { + pub fn serialize(&self, output: &mut [u8]) -> Result<(), ProgramError> { serialize_into(output, self).map_err(|err| match *err { ErrorKind::SizeLimit => ProgramError::UserdataTooSmall, _ => ProgramError::GenericError, @@ -85,9 +85,9 @@ mod tests { #[test] fn test_serde() { let mut buffer: Vec = vec![0; get_max_size()]; - let mut vote_program = VoteProgram::default(); + let mut vote_program = VoteState::default(); vote_program.votes = (0..MAX_VOTE_HISTORY).map(|_| Vote::default()).collect(); vote_program.serialize(&mut buffer).unwrap(); - assert_eq!(VoteProgram::deserialize(&buffer).unwrap(), vote_program); + assert_eq!(VoteState::deserialize(&buffer).unwrap(), vote_program); } } diff --git a/sdk/src/vote_transaction.rs b/sdk/src/vote_transaction.rs index 097edc5f0e..420743daed 100644 --- a/sdk/src/vote_transaction.rs +++ b/sdk/src/vote_transaction.rs @@ -13,15 +13,15 @@ pub struct VoteTransaction {} impl VoteTransaction { pub fn new_vote( - vote_account: &T, + voting_keypair: &T, tick_height: u64, last_id: Hash, fee: u64, ) -> Transaction { let vote = Vote { tick_height }; - let instruction = VoteInstruction::NewVote(vote); + let instruction = VoteInstruction::Vote(vote); Transaction::new( - vote_account, + voting_keypair, &[], vote_program::id(), &instruction, @@ -31,28 +31,25 @@ impl VoteTransaction { } pub fn new_account( - validator_id: &Keypair, + from_keypair: &Keypair, vote_account_id: Pubkey, last_id: Hash, num_tokens: u64, fee: u64, ) -> Transaction { + let create_tx = SystemInstruction::CreateAccount { + tokens: num_tokens, + space: vote_program::get_max_size() as u64, + program_id: vote_program::id(), + }; Transaction::new_with_instructions( - &[validator_id], + &[from_keypair], &[vote_account_id], last_id, fee, vec![system_program::id(), vote_program::id()], vec![ - Instruction::new( - 0, - &SystemInstruction::CreateAccount { - tokens: num_tokens, - space: vote_program::get_max_size() as u64, - program_id: vote_program::id(), - }, - vec![0, 1], - ), + Instruction::new(0, &create_tx, vec![0, 1]), Instruction::new(1, &VoteInstruction::RegisterAccount, vec![0, 1]), ], ) @@ -63,7 +60,7 @@ impl VoteTransaction { for i in 0..tx.instructions.len() { let tx_program_id = tx.program_id(i); if vote_program::check_id(&tx_program_id) { - if let Ok(Some(VoteInstruction::NewVote(vote))) = deserialize(&tx.userdata(i)) { + if let Ok(Some(VoteInstruction::Vote(vote))) = deserialize(&tx.userdata(i)) { votes.push((tx.account_keys[0], vote, tx.last_id)) } } diff --git a/src/compute_leader_confirmation_service.rs b/src/compute_leader_confirmation_service.rs index b856fe9b04..47888b303b 100644 --- a/src/compute_leader_confirmation_service.rs +++ b/src/compute_leader_confirmation_service.rs @@ -8,7 +8,7 @@ use crate::service::Service; use solana_metrics::{influxdb, submit}; use solana_sdk::pubkey::Pubkey; use solana_sdk::timing; -use solana_sdk::vote_program::{self, VoteProgram}; +use solana_sdk::vote_program::{self, VoteState}; use std::result; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; @@ -38,7 +38,7 @@ impl ComputeLeaderConfirmationService { // Hold an accounts_db read lock as briefly as possible, just long enough to collect all // the vote states - let vote_states: Vec = bank + let vote_states: Vec = bank .accounts .accounts_db .read() @@ -47,7 +47,7 @@ impl ComputeLeaderConfirmationService { .values() .filter_map(|account| { if vote_program::check_id(&account.owner) { - if let Ok(vote_state) = VoteProgram::deserialize(&account.userdata) { + if let Ok(vote_state) = VoteState::deserialize(&account.userdata) { if leader_id != vote_state.node_id { return Some(vote_state); } diff --git a/src/leader_scheduler.rs b/src/leader_scheduler.rs index 0d03355438..e5cb9ed3c2 100644 --- a/src/leader_scheduler.rs +++ b/src/leader_scheduler.rs @@ -12,7 +12,7 @@ use solana_sdk::hash::{hash, Hash}; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction::SystemTransaction; -use solana_sdk::vote_program::{self, VoteProgram}; +use solana_sdk::vote_program::{self, VoteState}; use solana_sdk::vote_transaction::VoteTransaction; use std::io::Cursor; use std::sync::Arc; @@ -335,7 +335,7 @@ impl LeaderScheduler { .values() .filter_map(|account| { if vote_program::check_id(&account.owner) { - if let Ok(vote_state) = VoteProgram::deserialize(&account.userdata) { + if let Ok(vote_state) = VoteState::deserialize(&account.userdata) { return vote_state .votes .back() diff --git a/src/thin_client.rs b/src/thin_client.rs index d49d06aa12..5b9f51d46c 100644 --- a/src/thin_client.rs +++ b/src/thin_client.rs @@ -473,7 +473,7 @@ mod tests { use bincode::{deserialize, serialize}; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; - use solana_sdk::vote_program::VoteProgram; + use solana_sdk::vote_program::VoteState; use solana_sdk::vote_transaction::VoteTransaction; use std::fs::remove_dir_all; @@ -592,7 +592,7 @@ mod tests { .expect("Expected valid response for account userdata") .expect("Expected valid account userdata to exist after account creation"); - let vote_state = VoteProgram::deserialize(&account_user_data); + let vote_state = VoteState::deserialize(&account_user_data); if vote_state.map(|vote_state| vote_state.node_id) == Ok(validator_keypair.pubkey()) { break;