From 18307b4b2c28ea6cd472cd5a2e694cf771e26b19 Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Mon, 31 Aug 2020 21:51:52 -0700 Subject: [PATCH] Ensure that the spl-token 2 native mint account is owned by the spl-token 2 program. Workaround for https://github.com/solana-labs/solana-program-library/issues/374 until spl-token 3 is shipped --- core/src/rpc.rs | 6 +-- runtime/src/bank.rs | 123 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 3 deletions(-) diff --git a/core/src/rpc.rs b/core/src/rpc.rs index 7a8b134fdca205..2aaf431d352dbb 100644 --- a/core/src/rpc.rs +++ b/core/src/rpc.rs @@ -2873,7 +2873,7 @@ pub mod tests { let largest_accounts: Vec = serde_json::from_value(json["result"]["value"].clone()) .expect("actual response deserialization"); - assert_eq!(largest_accounts.len(), 19); + assert_eq!(largest_accounts.len(), 20); // Get Alice balance let req = format!( @@ -2910,7 +2910,7 @@ pub mod tests { let largest_accounts: Vec = serde_json::from_value(json["result"]["value"].clone()) .expect("actual response deserialization"); - assert_eq!(largest_accounts.len(), 18); + assert_eq!(largest_accounts.len(), 19); let req = r#"{"jsonrpc":"2.0","id":1,"method":"getLargestAccounts","params":[{"filter":"nonCirculating"}]}"#; let res = io.handle_request_sync(&req, meta); let json: Value = serde_json::from_str(&res.unwrap()).unwrap(); @@ -4906,7 +4906,7 @@ pub mod tests { .expect("actual response deserialization"); let accounts: Vec = serde_json::from_value(result["result"].clone()).unwrap(); - assert_eq!(accounts.len(), 3); + assert_eq!(accounts.len(), 4); // Test returns only mint accounts let req = format!( diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 35a573cc650b20..5844c5fd0637ef 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -71,6 +71,29 @@ use std::{ sync::{Arc, RwLock, RwLockReadGuard}, }; +// Partial SPL Token v2.0.x declarations inlined to avoid an external dependency on the spl-token crate +pub mod inline_spl_token_v2_0 { + solana_sdk::declare_id!("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"); + pub mod native_mint { + solana_sdk::declare_id!("So11111111111111111111111111111111111111112"); + + /* + Mint { + mint_authority: COption::None, + supply: 0, + decimals: 9, + is_initialized: true, + freeze_authority: COption::None, + } + */ + pub const ACCOUNT_DATA: [u8; 82] = [ + 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 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, 0, 0, 0, 0, 0, + ]; + } +} + pub const SECONDS_PER_YEAR: f64 = 365.25 * 24.0 * 60.0 * 60.0; pub const MAX_LEADER_SCHEDULE_STAKES: Epoch = 5; @@ -3208,6 +3231,7 @@ impl Bank { self.reinvoke_entered_epoch_callback(initiate_callback); self.recheck_cross_program_support(); self.recheck_compute_budget(); + self.reconfigure_token2_native_mint(); } fn ensure_builtins(&mut self, init_or_warp: bool) { @@ -3257,6 +3281,39 @@ impl Bank { self.set_compute_budget(compute_budget); } + fn reconfigure_token2_native_mint(self: &mut Bank) { + let reconfigure_token2_native_mint = match self.operating_mode() { + OperatingMode::Development => true, + OperatingMode::Preview => self.epoch() == 93, + OperatingMode::Stable => self.epoch() == 75, + }; + + if reconfigure_token2_native_mint { + let mut native_mint_account = solana_sdk::account::Account { + owner: inline_spl_token_v2_0::id(), + data: inline_spl_token_v2_0::native_mint::ACCOUNT_DATA.to_vec(), + lamports: 1000000000, // 1 SOL + executable: false, + rent_epoch: self.epoch() + 1, + }; + + // As a workaround for + // https://github.com/solana-labs/solana-program-library/issues/374, ensure that the + // spl-token 2 native mint account is owned by the spl-token 2 program. + if let Some(existing_native_mint_account) = + self.get_account(&inline_spl_token_v2_0::native_mint::id()) + { + if existing_native_mint_account.owner == solana_sdk::system_program::id() { + native_mint_account.lamports = existing_native_mint_account.lamports; + } + } + self.store_account( + &inline_spl_token_v2_0::native_mint::id(), + &native_mint_account, + ); + } + } + fn fix_recent_blockhashes_sysvar_delay(&self) -> bool { let activation_slot = match self.operating_mode() { OperatingMode::Development => 0, @@ -8360,4 +8417,70 @@ mod tests { .unwrap() .add_native_program("mock_program", &program_id); } + + #[test] + fn test_reconfigure_token2_native_mint() { + solana_logger::setup(); + + let mut genesis_config = + create_genesis_config_with_leader(5, &Pubkey::new_rand(), 0).genesis_config; + + // OperatingMode::Development - Native mint exists immediately + assert_eq!(genesis_config.operating_mode, OperatingMode::Development); + let bank = Arc::new(Bank::new(&genesis_config)); + assert_eq!( + bank.get_balance(&inline_spl_token_v2_0::native_mint::id()), + 1000000000 + ); + + // OperatingMode::Preview - Native mint blinks into existence at epoch 93 + genesis_config.operating_mode = OperatingMode::Preview; + let bank = Arc::new(Bank::new(&genesis_config)); + assert_eq!( + bank.get_balance(&inline_spl_token_v2_0::native_mint::id()), + 0 + ); + bank.deposit(&inline_spl_token_v2_0::native_mint::id(), 4200000000); + + let bank = Bank::new_from_parent( + &bank, + &Pubkey::default(), + genesis_config.epoch_schedule.get_first_slot_in_epoch(93), + ); + + let native_mint_account = bank + .get_account(&inline_spl_token_v2_0::native_mint::id()) + .unwrap(); + assert_eq!(native_mint_account.data.len(), 82); + assert_eq!( + bank.get_balance(&inline_spl_token_v2_0::native_mint::id()), + 4200000000 + ); + assert_eq!(native_mint_account.owner, inline_spl_token_v2_0::id()); + + // OperatingMode::Stable - Native mint blinks into existence at epoch 75 + genesis_config.operating_mode = OperatingMode::Stable; + let bank = Arc::new(Bank::new(&genesis_config)); + assert_eq!( + bank.get_balance(&inline_spl_token_v2_0::native_mint::id()), + 0 + ); + bank.deposit(&inline_spl_token_v2_0::native_mint::id(), 4200000000); + + let bank = Bank::new_from_parent( + &bank, + &Pubkey::default(), + genesis_config.epoch_schedule.get_first_slot_in_epoch(75), + ); + + let native_mint_account = bank + .get_account(&inline_spl_token_v2_0::native_mint::id()) + .unwrap(); + assert_eq!(native_mint_account.data.len(), 82); + assert_eq!( + bank.get_balance(&inline_spl_token_v2_0::native_mint::id()), + 4200000000 + ); + assert_eq!(native_mint_account.owner, inline_spl_token_v2_0::id()); + } }