use highest staked node as bootstrap leader, remove bootstrap_leader from genesis_block (#4635)

* use highest staked node as bootstrap leader, remove bootstrap_leader from genesis_block

* clippy

* fixup

* fixup
This commit is contained in:
Rob Walker
2019-06-11 11:44:58 -07:00
committed by GitHub
parent 6dbba86cc6
commit 3217a1d70c
7 changed files with 45 additions and 14 deletions

View File

@ -391,7 +391,7 @@ impl Locktower {
let mut lockouts = VoteState::default(); let mut lockouts = VoteState::default();
if let Some(iter) = bank.epoch_vote_accounts(current_epoch) { if let Some(iter) = bank.epoch_vote_accounts(current_epoch) {
for (delegate_pubkey, (_, account)) in iter { for (delegate_pubkey, (_, account)) in iter {
if *delegate_pubkey == bank.collector_id() { if delegate_pubkey == bank.collector_id() {
let state = VoteState::deserialize(&account.data).expect("votes"); let state = VoteState::deserialize(&account.data).expect("votes");
if lockouts.votes.len() < state.votes.len() { if lockouts.votes.len() < state.votes.len() {
lockouts = state; lockouts = state;

View File

@ -388,7 +388,7 @@ impl ReplayStage {
for bank_slot in &active_banks { for bank_slot in &active_banks {
let bank = bank_forks.read().unwrap().get(*bank_slot).unwrap().clone(); let bank = bank_forks.read().unwrap().get(*bank_slot).unwrap().clone();
*ticks_per_slot = bank.ticks_per_slot(); *ticks_per_slot = bank.ticks_per_slot();
if bank.collector_id() != *my_pubkey { if bank.collector_id() != my_pubkey {
Self::replay_blocktree_into_bank(&bank, &blocktree, progress)?; Self::replay_blocktree_into_bank(&bank, &blocktree, progress)?;
} }
let max_tick_height = (*bank_slot + 1) * bank.ticks_per_slot() - 1; let max_tick_height = (*bank_slot + 1) * bank.ticks_per_slot() - 1;
@ -567,7 +567,7 @@ impl ReplayStage {
) { ) {
bank.freeze(); bank.freeze();
info!("bank frozen {}", bank.slot()); info!("bank frozen {}", bank.slot());
if let Err(e) = slot_full_sender.send((bank.slot(), bank.collector_id())) { if let Err(e) = slot_full_sender.send((bank.slot(), *bank.collector_id())) {
trace!("{} slot_full alert failed: {:?}", my_pubkey, e); trace!("{} slot_full alert failed: {:?}", my_pubkey, e);
} }
} }

View File

@ -247,7 +247,6 @@ fn main() -> Result<(), Box<dyn error::Error>> {
); );
let mut genesis_block = GenesisBlock::new( let mut genesis_block = GenesisBlock::new(
&bootstrap_leader_keypair.pubkey(),
&[ &[
// the mint // the mint
( (
@ -366,7 +365,7 @@ mod tests {
#[test] #[test]
fn test_append_primordial_accounts_to_genesis() { fn test_append_primordial_accounts_to_genesis() {
let mut genesis_block = GenesisBlock::new(&Pubkey::new_rand(), &[], &[]); let mut genesis_block = GenesisBlock::new(&[], &[]);
// Test invalid file returns error // Test invalid file returns error
assert!(append_primordial_accounts("unknownfile", &mut genesis_block).is_err()); assert!(append_primordial_accounts("unknownfile", &mut genesis_block).is_err());

View File

@ -345,8 +345,8 @@ impl Bank {
bank bank
} }
pub fn collector_id(&self) -> Pubkey { pub fn collector_id(&self) -> &Pubkey {
self.collector_id &self.collector_id
} }
pub fn slot(&self) -> u64 { pub fn slot(&self) -> u64 {
@ -473,13 +473,19 @@ impl Bank {
fn process_genesis_block(&mut self, genesis_block: &GenesisBlock) { fn process_genesis_block(&mut self, genesis_block: &GenesisBlock) {
// Bootstrap leader collects fees until `new_from_parent` is called. // Bootstrap leader collects fees until `new_from_parent` is called.
self.collector_id = genesis_block.bootstrap_leader_pubkey;
self.fee_calculator = genesis_block.fee_calculator.clone(); self.fee_calculator = genesis_block.fee_calculator.clone();
self.update_fees(); self.update_fees();
for (pubkey, account) in genesis_block.accounts.iter() { for (pubkey, account) in genesis_block.accounts.iter() {
self.store(pubkey, account); self.store(pubkey, account);
} }
// highest staked node is the first collector
self.collector_id = self
.stakes
.read()
.unwrap()
.highest_staked_node()
.unwrap_or_default();
self.blockhash_queue self.blockhash_queue
.write() .write()

View File

@ -39,7 +39,6 @@ pub fn create_genesis_block_with_leader(
); );
let genesis_block = GenesisBlock::new( let genesis_block = GenesisBlock::new(
&bootstrap_leader_pubkey,
&[ &[
// the mint // the mint
( (

View File

@ -3,6 +3,7 @@
use solana_sdk::account::Account; use solana_sdk::account::Account;
use solana_sdk::pubkey::Pubkey; use solana_sdk::pubkey::Pubkey;
use solana_stake_api::stake_state::StakeState; use solana_stake_api::stake_state::StakeState;
use solana_vote_api::vote_state::VoteState;
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize)] #[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize)]
@ -84,6 +85,14 @@ impl Stakes {
pub fn vote_accounts(&self) -> &HashMap<Pubkey, (u64, Account)> { pub fn vote_accounts(&self) -> &HashMap<Pubkey, (u64, Account)> {
&self.vote_accounts &self.vote_accounts
} }
pub fn highest_staked_node(&self) -> Option<Pubkey> {
self.vote_accounts
.iter()
.max_by(|(_ak, av), (_bk, bv)| av.0.cmp(&bv.0))
.and_then(|(_k, (_stake, account))| VoteState::from(account))
.map(|vote_state| vote_state.node_pubkey)
}
} }
#[cfg(test)] #[cfg(test)]
@ -153,6 +162,29 @@ mod tests {
} }
} }
#[test]
fn test_stakes_highest() {
let mut stakes = Stakes::default();
assert_eq!(stakes.highest_staked_node(), None);
let ((vote_pubkey, vote_account), (stake_pubkey, stake_account)) =
create_staked_node_accounts(10);
stakes.store(&vote_pubkey, &vote_account);
stakes.store(&stake_pubkey, &stake_account);
let ((vote11_pubkey, vote11_account), (stake11_pubkey, stake11_account)) =
create_staked_node_accounts(11);
stakes.store(&vote11_pubkey, &vote11_account);
stakes.store(&stake11_pubkey, &stake11_account);
let vote11_node_pubkey = VoteState::from(&vote11_account).unwrap().node_pubkey;
assert_eq!(stakes.highest_staked_node(), Some(vote11_node_pubkey))
}
#[test] #[test]
fn test_stakes_vote_account_disappear_reappear() { fn test_stakes_vote_account_disappear_reappear() {
let mut stakes = Stakes::default(); let mut stakes = Stakes::default();

View File

@ -15,7 +15,6 @@ use std::path::Path;
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct GenesisBlock { pub struct GenesisBlock {
pub accounts: Vec<(Pubkey, Account)>, pub accounts: Vec<(Pubkey, Account)>,
pub bootstrap_leader_pubkey: Pubkey,
pub epoch_warmup: bool, pub epoch_warmup: bool,
pub fee_calculator: FeeCalculator, pub fee_calculator: FeeCalculator,
pub native_instruction_processors: Vec<(String, Pubkey)>, pub native_instruction_processors: Vec<(String, Pubkey)>,
@ -30,7 +29,6 @@ pub fn create_genesis_block(lamports: u64) -> (GenesisBlock, Keypair) {
let mint_keypair = Keypair::new(); let mint_keypair = Keypair::new();
( (
GenesisBlock::new( GenesisBlock::new(
&Pubkey::default(),
&[( &[(
mint_keypair.pubkey(), mint_keypair.pubkey(),
Account::new(lamports, 0, &system_program::id()), Account::new(lamports, 0, &system_program::id()),
@ -43,13 +41,11 @@ pub fn create_genesis_block(lamports: u64) -> (GenesisBlock, Keypair) {
impl GenesisBlock { impl GenesisBlock {
pub fn new( pub fn new(
bootstrap_leader_pubkey: &Pubkey,
accounts: &[(Pubkey, Account)], accounts: &[(Pubkey, Account)],
native_instruction_processors: &[(String, Pubkey)], native_instruction_processors: &[(String, Pubkey)],
) -> Self { ) -> Self {
Self { Self {
accounts: accounts.to_vec(), accounts: accounts.to_vec(),
bootstrap_leader_pubkey: *bootstrap_leader_pubkey, // TODO: leader_schedule to derive from actual stakes, instead ;)
epoch_warmup: true, epoch_warmup: true,
fee_calculator: FeeCalculator::default(), fee_calculator: FeeCalculator::default(),
native_instruction_processors: native_instruction_processors.to_vec(), native_instruction_processors: native_instruction_processors.to_vec(),
@ -105,7 +101,6 @@ mod tests {
fn test_genesis_block() { fn test_genesis_block() {
let mint_keypair = Keypair::new(); let mint_keypair = Keypair::new();
let block = GenesisBlock::new( let block = GenesisBlock::new(
&Pubkey::default(),
&[ &[
( (
mint_keypair.pubkey(), mint_keypair.pubkey(),