diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 96d0d533f2..b8a57130c3 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -45,6 +45,7 @@ use solana_sdk::{ timing::years_as_slots, transaction::{Result, Transaction, TransactionError}, }; +use solana_stake_program::stake_state::Delegation; use solana_vote_program::vote_state::VoteState; use std::{ collections::HashMap, @@ -1630,6 +1631,12 @@ impl Bank { self.storage_accounts.read().unwrap().clone() } + /// current stake delegations for this bank + /// Note: this method is exposed publicly for external usage + pub fn stake_delegations(&self) -> HashMap { + self.stakes.read().unwrap().stake_delegations().clone() + } + /// current vote accounts for this bank along with the stake /// attributed to each account pub fn vote_accounts(&self) -> HashMap { @@ -1766,7 +1773,10 @@ mod tests { system_instruction, system_program, sysvar::{fees::Fees, rewards::Rewards}, }; - use solana_stake_program::stake_state::{self, Authorized, Delegation, Lockup, Stake}; + use solana_stake_program::{ + stake_instruction, + stake_state::{self, Authorized, Delegation, Lockup, Stake}, + }; use solana_vote_program::{ vote_instruction, vote_state::{self, Vote, VoteInit, VoteState, MAX_LOCKOUT_HISTORY}, @@ -3879,6 +3889,54 @@ mod tests { assert_eq!(vote_accounts.len(), 1); } + #[test] + fn test_bank_stake_delegations() { + let GenesisConfigInfo { + genesis_config, + mint_keypair, + .. + } = create_genesis_config_with_leader(500, &Pubkey::new_rand(), 1); + let bank = Arc::new(Bank::new(&genesis_config)); + + let stake_delegations = bank.stake_delegations(); + assert_eq!(stake_delegations.len(), 1); // bootstrap leader has + // to have a stake delegation + + let vote_keypair = Keypair::new(); + let mut instructions = vote_instruction::create_account( + &mint_keypair.pubkey(), + &vote_keypair.pubkey(), + &VoteInit { + node_pubkey: mint_keypair.pubkey(), + authorized_voter: vote_keypair.pubkey(), + authorized_withdrawer: vote_keypair.pubkey(), + commission: 0, + }, + 10, + ); + + let stake_keypair = Keypair::new(); + instructions.extend(stake_instruction::create_stake_account_and_delegate_stake( + &mint_keypair.pubkey(), + &stake_keypair.pubkey(), + &vote_keypair.pubkey(), + &Authorized::auto(&stake_keypair.pubkey()), + 10, + )); + + let transaction = Transaction::new_signed_instructions( + &[&mint_keypair, &vote_keypair, &stake_keypair], + instructions, + bank.last_blockhash(), + ); + + bank.process_transaction(&transaction).unwrap(); + + let stake_delegations = bank.stake_delegations(); + assert_eq!(stake_delegations.len(), 2); + assert!(stake_delegations.get(&stake_keypair.pubkey()).is_some()); + } + #[test] fn test_bank_fees_account() { let (mut genesis_config, _) = create_genesis_config(500); diff --git a/runtime/src/stakes.rs b/runtime/src/stakes.rs index 17ce884dfd..03d7d9cba5 100644 --- a/runtime/src/stakes.rs +++ b/runtime/src/stakes.rs @@ -178,6 +178,10 @@ impl Stakes { &self.vote_accounts } + pub fn stake_delegations(&self) -> &HashMap { + &self.stake_delegations + } + pub fn highest_staked_node(&self) -> Option { self.vote_accounts .iter()