diff --git a/Cargo.lock b/Cargo.lock index 2ffa8ab1c..21e812b87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2208,6 +2208,7 @@ dependencies = [ "solana-netutil 0.15.0", "solana-runtime 0.15.0", "solana-sdk 0.15.0", + "solana-stake-api 0.15.0", "solana-storage-api 0.15.0", "solana-vote-api 0.15.0", "solana-vote-program 0.15.0", @@ -2612,6 +2613,7 @@ dependencies = [ "solana-logger 0.15.0", "solana-metrics 0.15.0", "solana-sdk 0.15.0", + "solana-stake-api 0.15.0", "solana-vote-api 0.15.0", ] diff --git a/core/Cargo.toml b/core/Cargo.toml index 43ec0f198..f3ffce945 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -56,6 +56,7 @@ solana-metrics = { path = "../metrics", version = "0.15.0" } solana-netutil = { path = "../netutil", version = "0.15.0" } solana-runtime = { path = "../runtime", version = "0.15.0" } solana-sdk = { path = "../sdk", version = "0.15.0" } +solana-stake-api = { path = "../programs/stake_api", version = "0.15.0" } solana-storage-api = { path = "../programs/storage_api", version = "0.15.0" } solana-vote-api = { path = "../programs/vote_api", version = "0.15.0" } solana-vote-signer = { path = "../vote-signer", version = "0.15.0" } diff --git a/core/src/genesis_utils.rs b/core/src/genesis_utils.rs index ee6f4ea77..1d5296a66 100644 --- a/core/src/genesis_utils.rs +++ b/core/src/genesis_utils.rs @@ -1,46 +1,12 @@ -use solana_sdk::account::Account; +pub use solana_runtime::genesis_utils::{ + create_genesis_block_with_leader, BOOTSTRAP_LEADER_LAMPORTS, +}; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::pubkey::Pubkey; -use solana_sdk::signature::{Keypair, KeypairUtil}; -use solana_sdk::system_program; -use solana_vote_api::vote_state; +use solana_sdk::signature::Keypair; -// The default stake placed with the bootstrap leader -pub const BOOTSTRAP_LEADER_LAMPORTS: u64 = 42; - -pub fn create_genesis_block_with_leader( - mint_lamports: u64, - leader_id: &Pubkey, - leader_stake_lamports: u64, -) -> (GenesisBlock, Keypair, Keypair) { - let mint_keypair = Keypair::new(); - let voting_keypair = Keypair::new(); - - let genesis_block = GenesisBlock::new( - &leader_id, - &[ - ( - mint_keypair.pubkey(), - Account::new(mint_lamports, 0, &system_program::id()), - ), - ( - voting_keypair.pubkey(), - vote_state::create_bootstrap_leader_account( - &voting_keypair.pubkey(), - &leader_id, - 0, - leader_stake_lamports, - ), - ), - ], - &[], - ); - - (genesis_block, mint_keypair, voting_keypair) -} - -// same as genesis_block::create_genesis_block, but with leader staking logic specific -// to this crate +// same as genesis_block::create_genesis_block, but with bootstrap_leader staking logic +// for the core crate tests pub fn create_genesis_block(mint_lamports: u64) -> (GenesisBlock, Keypair) { let (genesis_block, mint_keypair, _vote_keypair) = create_genesis_block_with_leader( mint_lamports, diff --git a/core/src/leader_schedule_utils.rs b/core/src/leader_schedule_utils.rs index 0540cd1dd..dbadccda2 100644 --- a/core/src/leader_schedule_utils.rs +++ b/core/src/leader_schedule_utils.rs @@ -56,8 +56,10 @@ fn sort_stakes(stakes: &mut Vec<(Pubkey, u64)>) { #[cfg(test)] mod tests { use super::*; - use crate::genesis_utils::{create_genesis_block_with_leader, BOOTSTRAP_LEADER_LAMPORTS}; use crate::staking_utils; + use solana_runtime::genesis_utils::{ + create_genesis_block_with_leader, BOOTSTRAP_LEADER_LAMPORTS, + }; #[test] fn test_leader_schedule_via_bank() { diff --git a/genesis/src/main.rs b/genesis/src/main.rs index 2adee463e..a6f1ccda9 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -113,7 +113,8 @@ fn main() -> Result<(), Box> { &bootstrap_leader_keypair.pubkey(), 0, bootstrap_leader_lamports, - ), + ) + .0, ), ], &[ diff --git a/programs/vote_api/src/vote_state.rs b/programs/vote_api/src/vote_state.rs index f4910b831..466a35251 100644 --- a/programs/vote_api/src/vote_state.rs +++ b/programs/vote_api/src/vote_state.rs @@ -277,13 +277,15 @@ pub fn create_bootstrap_leader_account( node_id: &Pubkey, commission: u32, lamports: u64, -) -> Account { +) -> (Account, VoteState) { // Construct a vote account for the bootstrap_leader such that the leader_scheduler // will be forced to select it as the leader for height 0 - let mut account = create_account(&vote_id, &node_id, commission, lamports); + let mut vote_account = create_account(&vote_id, &node_id, commission, lamports); - vote(&vote_id, &mut account, &Vote::new(0)).unwrap(); - account + vote(&vote_id, &mut vote_account, &Vote::new(0)).unwrap(); + + let vote_state = vote_account.state().expect("account.state()"); + (vote_account, vote_state) } // utility function, used by Bank, tests @@ -332,6 +334,16 @@ mod tests { ) } + #[test] + fn test_vote_create_bootstrap_leader_account() { + let vote_id = Pubkey::new_rand(); + let (_vote_account, vote_state) = + vote_state::create_bootstrap_leader_account(&vote_id, &Pubkey::new_rand(), 0, 100); + + assert_eq!(vote_state.votes.len(), 1); + assert_eq!(vote_state.votes[0], Lockout::new(&Vote::new(0))); + } + #[test] fn test_vote_serialize() { let mut buffer: Vec = vec![0; VoteState::size_of()]; diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 66c35dd24..cf2d78d26 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -26,9 +26,9 @@ serde_json = "1.0.38" solana-logger = { path = "../logger", version = "0.15.0" } solana-metrics = { path = "../metrics", version = "0.15.0" } solana-sdk = { path = "../sdk", version = "0.15.0" } +solana-stake-api = { path = "../programs/stake_api", version = "0.15.0" } solana-vote-api = { path = "../programs/vote_api", version = "0.15.0" } [lib] name = "solana_runtime" crate-type = ["lib"] - diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 86fff4b48..42c91e76e 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -1042,52 +1042,17 @@ impl Drop for Bank { } #[cfg(test)] -pub(crate) mod tests { +mod tests { use super::*; - + use crate::genesis_utils::{create_genesis_block_with_leader, BOOTSTRAP_LEADER_LAMPORTS}; use solana_sdk::genesis_block::create_genesis_block; use solana_sdk::hash; use solana_sdk::instruction::InstructionError; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction; - use solana_sdk::system_program; use solana_sdk::system_transaction; use solana_vote_api::vote_instruction; - use solana_vote_api::vote_state::{self, VoteState}; - - // The default stake placed with the bootstrap leader - pub(crate) const BOOTSTRAP_LEADER_LAMPORTS: u64 = 42; - - pub(crate) fn create_genesis_block_with_leader( - mint_lamports: u64, - leader_id: &Pubkey, - leader_stake_lamports: u64, - ) -> (GenesisBlock, Keypair, Keypair) { - let mint_keypair = Keypair::new(); - let voting_keypair = Keypair::new(); - - let genesis_block = GenesisBlock::new( - &leader_id, - &[ - ( - mint_keypair.pubkey(), - Account::new(mint_lamports, 0, &system_program::id()), - ), - ( - voting_keypair.pubkey(), - vote_state::create_bootstrap_leader_account( - &voting_keypair.pubkey(), - &leader_id, - 0, - leader_stake_lamports, - ), - ), - ], - &[], - ); - - (genesis_block, mint_keypair, voting_keypair) - } + use solana_vote_api::vote_state::VoteState; #[test] fn test_bank_new() { diff --git a/runtime/src/genesis_utils.rs b/runtime/src/genesis_utils.rs new file mode 100644 index 000000000..9e521c044 --- /dev/null +++ b/runtime/src/genesis_utils.rs @@ -0,0 +1,60 @@ +use solana_sdk::account::Account; +use solana_sdk::genesis_block::GenesisBlock; +use solana_sdk::pubkey::Pubkey; +use solana_sdk::signature::{Keypair, KeypairUtil}; +use solana_sdk::system_program; +use solana_stake_api::stake_state; +use solana_vote_api::vote_state; + +// The default stake placed with the bootstrap leader +pub const BOOTSTRAP_LEADER_LAMPORTS: u64 = 42; + +pub fn create_genesis_block_with_leader( + mint_lamports: u64, + bootstrap_leader_id: &Pubkey, + bootstrap_leader_stake_lamports: u64, +) -> (GenesisBlock, Keypair, Keypair) { + let mint_keypair = Keypair::new(); + let voting_keypair = Keypair::new(); + let staking_keypair = Keypair::new(); + + // TODO: de-duplicate the stake once passive staking + // is fully implemented + let (vote_account, vote_state) = vote_state::create_bootstrap_leader_account( + &voting_keypair.pubkey(), + &bootstrap_leader_id, + 0, + bootstrap_leader_stake_lamports, + ); + + let genesis_block = GenesisBlock::new( + &bootstrap_leader_id, + &[ + // the mint + ( + mint_keypair.pubkey(), + Account::new(mint_lamports, 0, &system_program::id()), + ), + // node needs an account to issue votes from, this will require + // airdrops at some point to cover fees... + ( + *bootstrap_leader_id, + Account::new(1, 0, &system_program::id()), + ), + // where votes go to + (voting_keypair.pubkey(), vote_account), + // passive bootstrap leader stake, duplicates above temporarily + ( + staking_keypair.pubkey(), + stake_state::create_delegate_stake_account( + &voting_keypair.pubkey(), + &vote_state, + bootstrap_leader_stake_lamports, + ), + ), + ], + &[], + ); + + (genesis_block, mint_keypair, voting_keypair) +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 3a91d1b11..4a98a3c4a 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -6,6 +6,7 @@ pub mod bank; pub mod bank_client; mod blockhash_queue; pub mod bloom; +pub mod genesis_utils; pub mod loader_utils; pub mod locked_accounts_results; pub mod message_processor; diff --git a/runtime/src/locked_accounts_results.rs b/runtime/src/locked_accounts_results.rs index 908ec1d7c..5605bac87 100644 --- a/runtime/src/locked_accounts_results.rs +++ b/runtime/src/locked_accounts_results.rs @@ -53,7 +53,7 @@ impl<'a, 'b, I: Borrow> Drop for LockedAccountsResults<'a, 'b, I> { #[cfg(test)] mod tests { use super::*; - use crate::bank::tests::create_genesis_block_with_leader; + use crate::genesis_utils::create_genesis_block_with_leader; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_transaction;