diff --git a/Cargo.lock b/Cargo.lock index f625ad5f61..961c7d5a20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2143,9 +2143,14 @@ name = "solana-genesis" version = "0.13.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "solana 0.13.0", + "solana-budget-api 0.13.0", "solana-sdk 0.13.0", + "solana-storage-api 0.13.0", + "solana-token-api 0.13.0", + "solana-vote-api 0.13.0", ] [[package]] @@ -2266,12 +2271,9 @@ dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "solana-budget-api 0.13.0", "solana-logger 0.13.0", "solana-metrics 0.13.0", "solana-sdk 0.13.0", - "solana-storage-api 0.13.0", - "solana-token-api 0.13.0", "solana-vote-api 0.13.0", ] @@ -2402,6 +2404,7 @@ dependencies = [ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "solana 0.13.0", "solana-budget-api 0.13.0", + "solana-budget-program 0.13.0", "solana-drone 0.13.0", "solana-logger 0.13.0", "solana-sdk 0.13.0", @@ -2422,6 +2425,7 @@ dependencies = [ "reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "solana 0.13.0", + "solana-budget-program 0.13.0", "solana-logger 0.13.0", "solana-netutil 0.13.0", "solana-runtime 0.13.0", diff --git a/Cargo.toml b/Cargo.toml index 27bdeb124b..a3ba40e20f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,6 +31,7 @@ solana = { path = "core", version = "0.13.0" } solana-logger = { path = "logger", version = "0.13.0" } solana-netutil = { path = "netutil", version = "0.13.0" } solana-runtime = { path = "runtime", version = "0.13.0" } +solana-budget-program = { path = "programs/budget", version = "0.13.0" } solana-sdk = { path = "sdk", version = "0.13.0" } sys-info = "0.5.6" diff --git a/core/src/rpc_pubsub.rs b/core/src/rpc_pubsub.rs index 2776fb33a7..fb03cd8091 100644 --- a/core/src/rpc_pubsub.rs +++ b/core/src/rpc_pubsub.rs @@ -332,7 +332,13 @@ mod tests { #[test] fn test_account_subscribe() { - let (genesis_block, alice) = GenesisBlock::new(10_000); + let (mut genesis_block, alice) = GenesisBlock::new(10_000); + + // This test depends on the budget program + genesis_block + .native_programs + .push(("solana_budget_program".to_string(), solana_budget_api::id())); + let bob_pubkey = Keypair::new().pubkey(); let witness = Keypair::new(); let contract_funds = Keypair::new(); diff --git a/core/src/thin_client.rs b/core/src/thin_client.rs index 3ca882b0a5..715619ef11 100644 --- a/core/src/thin_client.rs +++ b/core/src/thin_client.rs @@ -423,7 +423,12 @@ pub fn new_fullnode() -> (Fullnode, ContactInfo, Keypair, String) { let node = Node::new_localhost_with_pubkey(&node_keypair.pubkey()); let contact_info = node.info.clone(); - let (genesis_block, mint_keypair) = GenesisBlock::new_with_leader(10_000, &contact_info.id, 42); + let (mut genesis_block, mint_keypair) = + GenesisBlock::new_with_leader(10_000, &contact_info.id, 42); + genesis_block + .native_programs + .push(("solana_budget_program".to_string(), solana_budget_api::id())); + let (ledger_path, _blockhash) = create_new_tmp_ledger!(&genesis_block); let voting_keypair = Keypair::new(); diff --git a/genesis/Cargo.toml b/genesis/Cargo.toml index 7b9d96565a..06e27fbfdc 100644 --- a/genesis/Cargo.toml +++ b/genesis/Cargo.toml @@ -13,6 +13,13 @@ clap = "2.32.0" serde_json = "1.0.39" solana = { path = "../core", version = "0.13.0" } solana-sdk = { path = "../sdk", version = "0.13.0" } +solana-budget-api = { path = "../programs/budget_api", version = "0.13.0" } +solana-storage-api = { path = "../programs/storage_api", version = "0.13.0" } +solana-token-api = { path = "../programs/token_api", version = "0.13.0" } + +[dev-dependencies] +hashbrown = "0.1.8" +solana-vote-api = { path = "../programs/vote_api", version = "0.13.0" } [features] cuda = ["solana/cuda"] diff --git a/genesis/src/main.rs b/genesis/src/main.rs index 627beb0519..67b5ddf945 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -70,7 +70,76 @@ fn main() -> Result<(), Box> { ); genesis_block.mint_id = mint_keypair.pubkey(); genesis_block.bootstrap_leader_vote_account_id = bootstrap_leader_vote_account_keypair.pubkey(); + genesis_block.native_programs.extend_from_slice(&[ + ("solana_budget_program".to_string(), solana_budget_api::id()), + ( + "solana_storage_program".to_string(), + solana_storage_api::id(), + ), + ("solana_token_program".to_string(), solana_token_api::id()), + ]); create_new_ledger(ledger_path, &genesis_block)?; Ok(()) } + +#[cfg(test)] +mod tests { + use hashbrown::HashSet; + use solana_sdk::pubkey::Pubkey; + + #[test] + fn test_program_ids() { + let system = Pubkey::new(&[ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ]); + let native = Pubkey::new(&[ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + ]); + let bpf = Pubkey::new(&[ + 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]); + let budget = Pubkey::new(&[ + 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]); + let storage = Pubkey::new(&[ + 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]); + let token = Pubkey::new(&[ + 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]); + let vote = Pubkey::new(&[ + 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, + ]); + + assert_eq!(solana_sdk::system_program::id(), system); + assert_eq!(solana_sdk::native_loader::id(), native); + assert_eq!(solana_sdk::bpf_loader::id(), bpf); + assert_eq!(solana_budget_api::id(), budget); + assert_eq!(solana_storage_api::id(), storage); + assert_eq!(solana_token_api::id(), token); + assert_eq!(solana_vote_api::id(), vote); + } + + #[test] + fn test_program_id_uniqueness() { + let mut unique = HashSet::new(); + let ids = vec![ + solana_sdk::system_program::id(), + solana_sdk::native_loader::id(), + solana_sdk::bpf_loader::id(), + solana_budget_api::id(), + solana_storage_api::id(), + solana_token_api::id(), + solana_vote_api::id(), + ]; + assert!(ids.into_iter().all(move |id| unique.insert(id))); + } +} diff --git a/programs/storage/tests/storage.rs b/programs/storage/tests/storage.rs index 69b7b5caa7..ff6ba2ddd8 100644 --- a/programs/storage/tests/storage.rs +++ b/programs/storage/tests/storage.rs @@ -37,7 +37,11 @@ fn get_storage_blockhash(bank: &Bank, account: &Pubkey) -> Hash { #[test] fn test_bank_storage() { - let (genesis_block, alice) = GenesisBlock::new(1000); + let (mut genesis_block, alice) = GenesisBlock::new(1000); + genesis_block.native_programs.push(( + "solana_storage_program".to_string(), + solana_storage_api::id(), + )); let bank = Bank::new(&genesis_block); let bob = Keypair::new(); diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index e2d4610316..380e8d4340 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -22,12 +22,9 @@ rand = "0.6.5" serde = "1.0.88" serde_derive = "1.0.88" serde_json = "1.0.38" -solana-budget-api = { path = "../programs/budget_api", version = "0.13.0" } solana-logger = { path = "../logger", version = "0.13.0" } solana-metrics = { path = "../metrics", version = "0.13.0" } solana-sdk = { path = "../sdk", version = "0.13.0" } -solana-storage-api = { path = "../programs/storage_api", version = "0.13.0" } -solana-token-api = { path = "../programs/token_api", version = "0.13.0" } solana-vote-api = { path = "../programs/vote_api", version = "0.13.0" } [lib] diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 57b51b77a7..e52cfcab6f 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -12,14 +12,12 @@ use hashbrown::HashMap; use log::*; use solana_metrics::counter::Counter; use solana_sdk::account::Account; -use solana_sdk::bpf_loader; use solana_sdk::genesis_block::GenesisBlock; use solana_sdk::hash::{extend_and_hash, Hash}; use solana_sdk::native_loader; use solana_sdk::native_program::ProgramError; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, Signature}; -use solana_sdk::system_program; use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::timing::{duration_as_us, MAX_RECENT_BLOCKHASHES, NUM_TICKS_PER_SECOND}; use solana_sdk::transaction::Transaction; @@ -211,7 +209,6 @@ impl Bank { let mut bank = Self::default(); bank.accounts = Some(Arc::new(Accounts::new(bank.slot, paths))); bank.process_genesis_block(genesis_block); - bank.add_builtin_programs(); // genesis needs stakes for all epochs up to the epoch implied by // slot = 0 and genesis configuration @@ -364,23 +361,25 @@ impl Bank { genesis_block.stakers_slot_offset, genesis_block.epoch_warmup, ); + + // Add native programs mandatory for the runtime to function + self.add_native_program("solana_system_program", &solana_sdk::system_program::id()); + self.add_native_program("solana_bpf_loader", &solana_sdk::bpf_loader::id()); + self.add_native_program("solana_vote_program", &solana_vote_api::id()); + + // Add additional native programs specified in the genesis block + for (name, program_id) in &genesis_block.native_programs { + self.add_native_program(name, program_id); + } } pub fn add_native_program(&self, name: &str, program_id: &Pubkey) { + debug!("Adding native program {} under {:?}", name, program_id); let account = native_loader::create_program_account(name); self.accounts() .store_slow(self.accounts_id, program_id, &account); } - fn add_builtin_programs(&self) { - self.add_native_program("solana_system_program", &system_program::id()); - self.add_native_program("solana_vote_program", &solana_vote_api::id()); - self.add_native_program("solana_storage_program", &solana_storage_api::id()); - self.add_native_program("solana_bpf_loader", &bpf_loader::id()); - self.add_native_program("solana_budget_program", &solana_budget_api::id()); - self.add_native_program("solana_token_program", &solana_token_api::id()); - } - /// Return the last block hash registered. pub fn last_blockhash(&self) -> Hash { self.blockhash_queue.read().unwrap().last_hash() @@ -889,11 +888,11 @@ impl Bank { mod tests { use super::*; use bincode::serialize; - use hashbrown::HashSet; use solana_sdk::genesis_block::{GenesisBlock, BOOTSTRAP_LEADER_LAMPORTS}; use solana_sdk::native_program::ProgramError; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::system_instruction::SystemInstruction; + use solana_sdk::system_program; use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::transaction::Instruction; @@ -1281,61 +1280,6 @@ mod tests { .is_ok()); } - #[test] - fn test_program_ids() { - let system = Pubkey::new(&[ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]); - let native = Pubkey::new(&[ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - ]); - let bpf = Pubkey::new(&[ - 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]); - let budget = Pubkey::new(&[ - 129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]); - let storage = Pubkey::new(&[ - 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]); - let token = Pubkey::new(&[ - 131, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]); - let vote = Pubkey::new(&[ - 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, - ]); - - assert_eq!(system_program::id(), system); - assert_eq!(native_loader::id(), native); - assert_eq!(bpf_loader::id(), bpf); - assert_eq!(solana_budget_api::id(), budget); - assert_eq!(solana_storage_api::id(), storage); - assert_eq!(solana_token_api::id(), token); - assert_eq!(solana_vote_api::id(), vote); - } - - #[test] - fn test_program_id_uniqueness() { - let mut unique = HashSet::new(); - let ids = vec![ - system_program::id(), - native_loader::id(), - bpf_loader::id(), - solana_budget_api::id(), - solana_storage_api::id(), - solana_token_api::id(), - solana_vote_api::id(), - ]; - assert!(ids.into_iter().all(move |id| unique.insert(id))); - } - #[test] fn test_bank_pay_to_self() { let (genesis_block, mint_keypair) = GenesisBlock::new(1); diff --git a/sdk/src/genesis_block.rs b/sdk/src/genesis_block.rs index 81ea0ba6bf..394f0e5b1a 100644 --- a/sdk/src/genesis_block.rs +++ b/sdk/src/genesis_block.rs @@ -24,6 +24,7 @@ pub struct GenesisBlock { pub slots_per_epoch: u64, pub stakers_slot_offset: u64, pub epoch_warmup: bool, + pub native_programs: Vec<(String, Pubkey)>, } impl GenesisBlock { @@ -57,6 +58,7 @@ impl GenesisBlock { slots_per_epoch: DEFAULT_SLOTS_PER_EPOCH, stakers_slot_offset: DEFAULT_SLOTS_PER_EPOCH, epoch_warmup: true, + native_programs: vec![], }, mint_keypair, ) diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index bad047f5b1..ff13928fe7 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -24,5 +24,8 @@ solana-sdk = { path = "../sdk", version = "0.13.0" } solana-vote-api = { path = "../programs/vote_api", version = "0.13.0" } solana-vote-signer = { path = "../vote-signer", version = "0.13.0" } +[dev-dependencies] +solana-budget-program = { path = "../programs/budget", version = "0.13.0" } + [features] cuda = ["solana/cuda"]