diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 51928dd804..83222d4a09 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -5012,10 +5012,11 @@ pub(crate) mod tests { stake_instruction, stake_state::{self, Authorized, Delegation, Lockup, Stake}, }; - use solana_vote_program::vote_state::VoteStateVersions; use solana_vote_program::{ vote_instruction, - vote_state::{self, BlockTimestamp, Vote, VoteInit, VoteState, MAX_LOCKOUT_HISTORY}, + vote_state::{ + self, BlockTimestamp, Vote, VoteInit, VoteState, VoteStateVersions, MAX_LOCKOUT_HISTORY, + }, }; use std::{result, thread::Builder, time::Duration}; @@ -12153,4 +12154,72 @@ pub(crate) mod tests { let stake_delegation_accounts = bank.stake_delegation_accounts(&mut null_tracer()); assert_eq!(stake_delegation_accounts.len(), 0); } + + #[test] + fn test_vote_epoch_panic() { + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config_with_leader( + 1_000_000_000_000_000, + &Pubkey::new_unique(), + bootstrap_validator_stake_lamports(), + ); + let bank = Arc::new(Bank::new(&genesis_config)); + + let vote_keypair = keypair_from_seed(&[1u8; 32]).unwrap(); + let stake_keypair = keypair_from_seed(&[2u8; 32]).unwrap(); + + let mut setup_ixs = Vec::new(); + setup_ixs.extend( + vote_instruction::create_account( + &mint_keypair.pubkey(), + &vote_keypair.pubkey(), + &VoteInit { + node_pubkey: mint_keypair.pubkey(), + authorized_voter: vote_keypair.pubkey(), + authorized_withdrawer: mint_keypair.pubkey(), + commission: 0, + }, + 1_000_000_000, + ) + .into_iter(), + ); + setup_ixs.extend( + stake_instruction::create_account_and_delegate_stake( + &mint_keypair.pubkey(), + &stake_keypair.pubkey(), + &vote_keypair.pubkey(), + &Authorized::auto(&mint_keypair.pubkey()), + &Lockup::default(), + 1_000_000_000_000, + ) + .into_iter(), + ); + setup_ixs.push(vote_instruction::withdraw( + &vote_keypair.pubkey(), + &mint_keypair.pubkey(), + 1_000_000_000, + &mint_keypair.pubkey(), + )); + setup_ixs.push(system_instruction::transfer( + &mint_keypair.pubkey(), + &vote_keypair.pubkey(), + 1_000_000_000, + )); + + let result = bank.process_transaction(&Transaction::new( + &[&mint_keypair, &vote_keypair, &stake_keypair], + Message::new(&setup_ixs, Some(&mint_keypair.pubkey())), + bank.last_blockhash(), + )); + assert!(result.is_ok()); + + let _bank = Bank::new_from_parent( + &bank, + &mint_keypair.pubkey(), + genesis_config.epoch_schedule.get_first_slot_in_epoch(1), + ); + } } diff --git a/runtime/src/epoch_stakes.rs b/runtime/src/epoch_stakes.rs index b50cafaffc..02d14f92c5 100644 --- a/runtime/src/epoch_stakes.rs +++ b/runtime/src/epoch_stakes.rs @@ -83,21 +83,23 @@ impl EpochStakes { } Ok(vote_state) => vote_state, }; + if *stake > 0 { - // Read out the authorized voters - let authorized_voter = vote_state + if let Some(authorized_voter) = vote_state .authorized_voters() .get_authorized_voter(leader_schedule_epoch) - .expect("Authorized voter for current epoch must be known"); + { + let node_vote_accounts = node_id_to_vote_accounts + .entry(vote_state.node_pubkey) + .or_default(); - let node_vote_accounts = node_id_to_vote_accounts - .entry(vote_state.node_pubkey) - .or_default(); + node_vote_accounts.total_stake += stake; + node_vote_accounts.vote_accounts.push(*key); - node_vote_accounts.total_stake += stake; - node_vote_accounts.vote_accounts.push(*key); - - Some((*key, authorized_voter)) + Some((*key, authorized_voter)) + } else { + None + } } else { None }