Sfoglia il codice sorgente

Fix BankForks::new_rw_arc memory leak (#1893)

Andrei Silviu Dragnea 1 anno fa
parent
commit
d441c0f577

+ 9 - 7
bench-tps/src/bench.rs

@@ -1223,7 +1223,7 @@ pub fn fund_keypairs<T: 'static + TpsClient + Send + Sync + ?Sized>(
 mod tests {
 mod tests {
     use {
     use {
         super::*,
         super::*,
-        solana_runtime::{bank::Bank, bank_client::BankClient},
+        solana_runtime::{bank::Bank, bank_client::BankClient, bank_forks::BankForks},
         solana_sdk::{
         solana_sdk::{
             commitment_config::CommitmentConfig,
             commitment_config::CommitmentConfig,
             feature_set::FeatureSet,
             feature_set::FeatureSet,
@@ -1234,16 +1234,18 @@ mod tests {
         },
         },
     };
     };
 
 
-    fn bank_with_all_features(genesis_config: &GenesisConfig) -> Arc<Bank> {
+    fn bank_with_all_features(
+        genesis_config: &GenesisConfig,
+    ) -> (Arc<Bank>, Arc<RwLock<BankForks>>) {
         let mut bank = Bank::new_for_tests(genesis_config);
         let mut bank = Bank::new_for_tests(genesis_config);
         bank.feature_set = Arc::new(FeatureSet::all_enabled());
         bank.feature_set = Arc::new(FeatureSet::all_enabled());
-        bank.wrap_with_bank_forks_for_tests().0
+        bank.wrap_with_bank_forks_for_tests()
     }
     }
 
 
     #[test]
     #[test]
     fn test_bench_tps_bank_client() {
     fn test_bench_tps_bank_client() {
         let (genesis_config, id) = create_genesis_config(sol_to_lamports(10_000.0));
         let (genesis_config, id) = create_genesis_config(sol_to_lamports(10_000.0));
-        let bank = bank_with_all_features(&genesis_config);
+        let (bank, _bank_forks) = bank_with_all_features(&genesis_config);
         let client = Arc::new(BankClient::new_shared(bank));
         let client = Arc::new(BankClient::new_shared(bank));
 
 
         let config = Config {
         let config = Config {
@@ -1264,7 +1266,7 @@ mod tests {
     #[test]
     #[test]
     fn test_bench_tps_fund_keys() {
     fn test_bench_tps_fund_keys() {
         let (genesis_config, id) = create_genesis_config(sol_to_lamports(10_000.0));
         let (genesis_config, id) = create_genesis_config(sol_to_lamports(10_000.0));
-        let bank = bank_with_all_features(&genesis_config);
+        let (bank, _bank_forks) = bank_with_all_features(&genesis_config);
         let client = Arc::new(BankClient::new_shared(bank));
         let client = Arc::new(BankClient::new_shared(bank));
         let keypair_count = 20;
         let keypair_count = 20;
         let lamports = 20;
         let lamports = 20;
@@ -1289,7 +1291,7 @@ mod tests {
         let (mut genesis_config, id) = create_genesis_config(sol_to_lamports(10_000.0));
         let (mut genesis_config, id) = create_genesis_config(sol_to_lamports(10_000.0));
         let fee_rate_governor = FeeRateGovernor::new(11, 0);
         let fee_rate_governor = FeeRateGovernor::new(11, 0);
         genesis_config.fee_rate_governor = fee_rate_governor;
         genesis_config.fee_rate_governor = fee_rate_governor;
-        let bank = bank_with_all_features(&genesis_config);
+        let (bank, _bank_forks) = bank_with_all_features(&genesis_config);
         let client = Arc::new(BankClient::new_shared(bank));
         let client = Arc::new(BankClient::new_shared(bank));
         let keypair_count = 20;
         let keypair_count = 20;
         let lamports = 20;
         let lamports = 20;
@@ -1307,7 +1309,7 @@ mod tests {
     #[test]
     #[test]
     fn test_bench_tps_create_durable_nonce() {
     fn test_bench_tps_create_durable_nonce() {
         let (genesis_config, id) = create_genesis_config(sol_to_lamports(10_000.0));
         let (genesis_config, id) = create_genesis_config(sol_to_lamports(10_000.0));
-        let bank = bank_with_all_features(&genesis_config);
+        let (bank, _bank_forks) = bank_with_all_features(&genesis_config);
         let client = Arc::new(BankClient::new_shared(bank));
         let client = Arc::new(BankClient::new_shared(bank));
         let keypair_count = 10;
         let keypair_count = 10;
         let lamports = 10_000_000;
         let lamports = 10_000_000;

+ 1 - 1
core/benches/banking_stage.rs

@@ -398,7 +398,7 @@ fn simulate_process_entries(
     let bank_fork = BankForks::new_rw_arc(bank);
     let bank_fork = BankForks::new_rw_arc(bank);
     let bank = bank_fork.read().unwrap().get_with_scheduler(slot).unwrap();
     let bank = bank_fork.read().unwrap().get_with_scheduler(slot).unwrap();
     bank.clone_without_scheduler()
     bank.clone_without_scheduler()
-        .set_fork_graph_in_program_cache(bank_fork.clone());
+        .set_fork_graph_in_program_cache(Arc::downgrade(&bank_fork));
 
 
     for i in 0..(num_accounts / 2) {
     for i in 0..(num_accounts / 2) {
         bank.transfer(initial_lamports, mint_keypair, &keypairs[i * 2].pubkey())
         bank.transfer(initial_lamports, mint_keypair, &keypairs[i * 2].pubkey())

+ 5 - 2
core/benches/consumer.rs

@@ -19,7 +19,7 @@ use {
         poh_recorder::{create_test_recorder, PohRecorder},
         poh_recorder::{create_test_recorder, PohRecorder},
         poh_service::PohService,
         poh_service::PohService,
     },
     },
-    solana_runtime::bank::Bank,
+    solana_runtime::{bank::Bank, bank_forks::BankForks},
     solana_sdk::{
     solana_sdk::{
         account::{Account, ReadableAccount},
         account::{Account, ReadableAccount},
         signature::Keypair,
         signature::Keypair,
@@ -89,6 +89,7 @@ fn create_consumer(poh_recorder: &RwLock<PohRecorder>) -> Consumer {
 
 
 struct BenchFrame {
 struct BenchFrame {
     bank: Arc<Bank>,
     bank: Arc<Bank>,
+    _bank_forks: Arc<RwLock<BankForks>>,
     ledger_path: TempDir,
     ledger_path: TempDir,
     exit: Arc<AtomicBool>,
     exit: Arc<AtomicBool>,
     poh_recorder: Arc<RwLock<PohRecorder>>,
     poh_recorder: Arc<RwLock<PohRecorder>>,
@@ -115,7 +116,7 @@ fn setup() -> BenchFrame {
     bank.write_cost_tracker()
     bank.write_cost_tracker()
         .unwrap()
         .unwrap()
         .set_limits(u64::MAX, u64::MAX, u64::MAX);
         .set_limits(u64::MAX, u64::MAX, u64::MAX);
-    let bank = bank.wrap_with_bank_forks_for_tests().0;
+    let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
 
 
     let ledger_path = TempDir::new().unwrap();
     let ledger_path = TempDir::new().unwrap();
     let blockstore = Arc::new(
     let blockstore = Arc::new(
@@ -126,6 +127,7 @@ fn setup() -> BenchFrame {
 
 
     BenchFrame {
     BenchFrame {
         bank,
         bank,
+        _bank_forks: bank_forks,
         ledger_path,
         ledger_path,
         exit,
         exit,
         poh_recorder,
         poh_recorder,
@@ -147,6 +149,7 @@ fn bench_process_and_record_transactions(bencher: &mut Bencher, batch_size: usiz
 
 
     let BenchFrame {
     let BenchFrame {
         bank,
         bank,
+        _bank_forks,
         ledger_path: _ledger_path,
         ledger_path: _ledger_path,
         exit,
         exit,
         poh_recorder,
         poh_recorder,

+ 3 - 3
core/src/banking_stage.rs

@@ -1064,7 +1064,7 @@ mod tests {
             drop(poh_recorder);
             drop(poh_recorder);
 
 
             let mut blockhash = start_hash;
             let mut blockhash = start_hash;
-            let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+            let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
             bank.process_transaction(&fund_tx).unwrap();
             bank.process_transaction(&fund_tx).unwrap();
             //receive entries + ticks
             //receive entries + ticks
             loop {
             loop {
@@ -1208,7 +1208,7 @@ mod tests {
                 .map(|(_bank, (entry, _tick_height))| entry)
                 .map(|(_bank, (entry, _tick_height))| entry)
                 .collect();
                 .collect();
 
 
-            let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+            let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
             for entry in entries {
             for entry in entries {
                 bank.process_entry_transactions(entry.transactions)
                 bank.process_entry_transactions(entry.transactions)
                     .iter()
                     .iter()
@@ -1232,7 +1232,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(10_000);
         } = create_genesis_config(10_000);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         {
         {
             let blockstore = Blockstore::open(ledger_path.path())
             let blockstore = Blockstore::open(ledger_path.path())

+ 5 - 2
core/src/banking_stage/consume_worker.rs

@@ -710,7 +710,8 @@ mod tests {
         },
         },
         solana_poh::poh_recorder::{PohRecorder, WorkingBankEntry},
         solana_poh::poh_recorder::{PohRecorder, WorkingBankEntry},
         solana_runtime::{
         solana_runtime::{
-            prioritization_fee_cache::PrioritizationFeeCache, vote_sender_types::ReplayVoteReceiver,
+            bank_forks::BankForks, prioritization_fee_cache::PrioritizationFeeCache,
+            vote_sender_types::ReplayVoteReceiver,
         },
         },
         solana_sdk::{
         solana_sdk::{
             genesis_config::GenesisConfig, poh_config::PohConfig, pubkey::Pubkey,
             genesis_config::GenesisConfig, poh_config::PohConfig, pubkey::Pubkey,
@@ -729,6 +730,7 @@ mod tests {
         mint_keypair: Keypair,
         mint_keypair: Keypair,
         genesis_config: GenesisConfig,
         genesis_config: GenesisConfig,
         bank: Arc<Bank>,
         bank: Arc<Bank>,
+        _bank_forks: Arc<RwLock<BankForks>>,
         _ledger_path: TempDir,
         _ledger_path: TempDir,
         _entry_receiver: Receiver<WorkingBankEntry>,
         _entry_receiver: Receiver<WorkingBankEntry>,
         poh_recorder: Arc<RwLock<PohRecorder>>,
         poh_recorder: Arc<RwLock<PohRecorder>>,
@@ -745,7 +747,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_slow_genesis_config(10_000);
         } = create_slow_genesis_config(10_000);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
 
 
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let blockstore = Blockstore::open(ledger_path.path())
         let blockstore = Blockstore::open(ledger_path.path())
@@ -788,6 +790,7 @@ mod tests {
                 mint_keypair,
                 mint_keypair,
                 genesis_config,
                 genesis_config,
                 bank,
                 bank,
+                _bank_forks: bank_forks,
                 _ledger_path: ledger_path,
                 _ledger_path: ledger_path,
                 _entry_receiver: entry_receiver,
                 _entry_receiver: entry_receiver,
                 poh_recorder,
                 poh_recorder,

+ 33 - 17
core/src/banking_stage/consumer.rs

@@ -851,7 +851,7 @@ mod tests {
         solana_poh::poh_recorder::{PohRecorder, Record, WorkingBankEntry},
         solana_poh::poh_recorder::{PohRecorder, Record, WorkingBankEntry},
         solana_program_runtime::timings::ProgramTiming,
         solana_program_runtime::timings::ProgramTiming,
         solana_rpc::transaction_status_service::TransactionStatusService,
         solana_rpc::transaction_status_service::TransactionStatusService,
-        solana_runtime::prioritization_fee_cache::PrioritizationFeeCache,
+        solana_runtime::{bank_forks::BankForks, prioritization_fee_cache::PrioritizationFeeCache},
         solana_sdk::{
         solana_sdk::{
             account::AccountSharedData,
             account::AccountSharedData,
             account_utils::StateMut,
             account_utils::StateMut,
@@ -989,6 +989,7 @@ mod tests {
     ) -> (
     ) -> (
         Vec<Transaction>,
         Vec<Transaction>,
         Arc<Bank>,
         Arc<Bank>,
+        Arc<RwLock<BankForks>>,
         Arc<RwLock<PohRecorder>>,
         Arc<RwLock<PohRecorder>>,
         Receiver<WorkingBankEntry>,
         Receiver<WorkingBankEntry>,
         GenesisConfigInfo,
         GenesisConfigInfo,
@@ -1003,7 +1004,7 @@ mod tests {
         } = &genesis_config_info;
         } = &genesis_config_info;
         let blockstore =
         let blockstore =
             Blockstore::open(ledger_path).expect("Expected to be able to open database ledger");
             Blockstore::open(ledger_path).expect("Expected to be able to open database ledger");
-        let bank = Bank::new_no_wallclock_throttle_for_tests(genesis_config).0;
+        let (bank, bank_forks) = Bank::new_no_wallclock_throttle_for_tests(genesis_config);
         let exit = Arc::new(AtomicBool::default());
         let exit = Arc::new(AtomicBool::default());
         let (poh_recorder, entry_receiver, record_receiver) = PohRecorder::new(
         let (poh_recorder, entry_receiver, record_receiver) = PohRecorder::new(
             bank.tick_height(),
             bank.tick_height(),
@@ -1032,6 +1033,7 @@ mod tests {
         (
         (
             transactions,
             transactions,
             bank,
             bank,
+            bank_forks,
             poh_recorder,
             poh_recorder,
             entry_receiver,
             entry_receiver,
             genesis_config_info,
             genesis_config_info,
@@ -1059,7 +1061,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_slow_genesis_config(10_000);
         } = create_slow_genesis_config(10_000);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey = solana_sdk::pubkey::new_rand();
 
 
         let transactions = sanitize_transactions(vec![system_transaction::transfer(
         let transactions = sanitize_transactions(vec![system_transaction::transfer(
@@ -1187,7 +1189,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_slow_genesis_config(10_000);
         } = create_slow_genesis_config(10_000);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         let pubkey = Pubkey::new_unique();
         let pubkey = Pubkey::new_unique();
 
 
         // setup nonce account with a durable nonce different from the current
         // setup nonce account with a durable nonce different from the current
@@ -1343,7 +1345,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_slow_genesis_config(10_000);
         } = create_slow_genesis_config(10_000);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey = solana_sdk::pubkey::new_rand();
 
 
         let transactions = {
         let transactions = {
@@ -1427,7 +1429,7 @@ mod tests {
         } = create_slow_genesis_config(10_000);
         } = create_slow_genesis_config(10_000);
         let mut bank = Bank::new_for_tests(&genesis_config);
         let mut bank = Bank::new_for_tests(&genesis_config);
         bank.ns_per_slot = u128::MAX;
         bank.ns_per_slot = u128::MAX;
-        let bank = bank.wrap_with_bank_forks_for_tests().0;
+        let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests();
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey = solana_sdk::pubkey::new_rand();
 
 
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
@@ -1583,7 +1585,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_slow_genesis_config(10_000);
         } = create_slow_genesis_config(10_000);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey1 = solana_sdk::pubkey::new_rand();
         let pubkey1 = solana_sdk::pubkey::new_rand();
 
 
@@ -1660,7 +1662,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_slow_genesis_config(lamports);
         } = create_slow_genesis_config(lamports);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         // set cost tracker limits to MAX so it will not filter out TXs
         // set cost tracker limits to MAX so it will not filter out TXs
         bank.write_cost_tracker()
         bank.write_cost_tracker()
             .unwrap()
             .unwrap()
@@ -1721,7 +1723,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_slow_genesis_config(10_000);
         } = create_slow_genesis_config(10_000);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         // set cost tracker limits to MAX so it will not filter out TXs
         // set cost tracker limits to MAX so it will not filter out TXs
         bank.write_cost_tracker()
         bank.write_cost_tracker()
             .unwrap()
             .unwrap()
@@ -1780,7 +1782,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_slow_genesis_config(10_000);
         } = create_slow_genesis_config(10_000);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
 
 
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey = solana_sdk::pubkey::new_rand();
 
 
@@ -1861,7 +1863,7 @@ mod tests {
         } = create_slow_genesis_config(solana_sdk::native_token::sol_to_lamports(1000.0));
         } = create_slow_genesis_config(solana_sdk::native_token::sol_to_lamports(1000.0));
         genesis_config.rent.lamports_per_byte_year = 50;
         genesis_config.rent.lamports_per_byte_year = 50;
         genesis_config.rent.exemption_threshold = 2.0;
         genesis_config.rent.exemption_threshold = 2.0;
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey1 = solana_sdk::pubkey::new_rand();
         let pubkey1 = solana_sdk::pubkey::new_rand();
         let keypair1 = Keypair::new();
         let keypair1 = Keypair::new();
@@ -2130,7 +2132,7 @@ mod tests {
     fn test_consume_buffered_packets() {
     fn test_consume_buffered_packets() {
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         {
         {
-            let (transactions, bank, poh_recorder, _entry_receiver, _, poh_simulator) =
+            let (transactions, bank, _bank_forks, poh_recorder, _entry_receiver, _, poh_simulator) =
                 setup_conflicting_transactions(ledger_path.path());
                 setup_conflicting_transactions(ledger_path.path());
             let recorder: TransactionRecorder = poh_recorder.read().unwrap().new_recorder();
             let recorder: TransactionRecorder = poh_recorder.read().unwrap().new_recorder();
             let num_conflicting_transactions = transactions.len();
             let num_conflicting_transactions = transactions.len();
@@ -2203,8 +2205,15 @@ mod tests {
     fn test_consume_buffered_packets_sanitization_error() {
     fn test_consume_buffered_packets_sanitization_error() {
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         {
         {
-            let (mut transactions, bank, poh_recorder, _entry_receiver, _, poh_simulator) =
-                setup_conflicting_transactions(ledger_path.path());
+            let (
+                mut transactions,
+                bank,
+                _bank_forks,
+                poh_recorder,
+                _entry_receiver,
+                _,
+                poh_simulator,
+            ) = setup_conflicting_transactions(ledger_path.path());
             let duplicate_account_key = transactions[0].message.account_keys[0];
             let duplicate_account_key = transactions[0].message.account_keys[0];
             transactions[0]
             transactions[0]
                 .message
                 .message
@@ -2259,7 +2268,7 @@ mod tests {
     fn test_consume_buffered_packets_retryable() {
     fn test_consume_buffered_packets_retryable() {
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         {
         {
-            let (transactions, bank, poh_recorder, _entry_receiver, _, poh_simulator) =
+            let (transactions, bank, _bank_forks, poh_recorder, _entry_receiver, _, poh_simulator) =
                 setup_conflicting_transactions(ledger_path.path());
                 setup_conflicting_transactions(ledger_path.path());
             let recorder = poh_recorder.read().unwrap().new_recorder();
             let recorder = poh_recorder.read().unwrap().new_recorder();
             let num_conflicting_transactions = transactions.len();
             let num_conflicting_transactions = transactions.len();
@@ -2355,8 +2364,15 @@ mod tests {
     fn test_consume_buffered_packets_batch_priority_guard() {
     fn test_consume_buffered_packets_batch_priority_guard() {
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         {
         {
-            let (_, bank, poh_recorder, _entry_receiver, genesis_config_info, poh_simulator) =
-                setup_conflicting_transactions(ledger_path.path());
+            let (
+                _,
+                bank,
+                _bank_forks,
+                poh_recorder,
+                _entry_receiver,
+                genesis_config_info,
+                poh_simulator,
+            ) = setup_conflicting_transactions(ledger_path.path());
             let recorder = poh_recorder.read().unwrap().new_recorder();
             let recorder = poh_recorder.read().unwrap().new_recorder();
 
 
             // Setup transactions:
             // Setup transactions:

+ 1 - 1
core/src/banking_stage/decision_maker.rs

@@ -148,7 +148,7 @@ mod tests {
     #[test]
     #[test]
     fn test_make_consume_or_forward_decision() {
     fn test_make_consume_or_forward_decision() {
         let genesis_config = create_genesis_config(2).genesis_config;
         let genesis_config = create_genesis_config(2).genesis_config;
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         let ledger_path = temp_dir();
         let ledger_path = temp_dir();
         let blockstore = Arc::new(Blockstore::open(ledger_path.as_path()).unwrap());
         let blockstore = Arc::new(Blockstore::open(ledger_path.as_path()).unwrap());
         let (exit, poh_recorder, poh_service, _entry_receiver) =
         let (exit, poh_recorder, poh_service, _entry_receiver) =

+ 8 - 5
core/src/banking_stage/read_write_account_set.rs

@@ -84,7 +84,7 @@ mod tests {
     use {
     use {
         super::ReadWriteAccountSet,
         super::ReadWriteAccountSet,
         solana_ledger::genesis_utils::GenesisConfigInfo,
         solana_ledger::genesis_utils::GenesisConfigInfo,
-        solana_runtime::{bank::Bank, genesis_utils::create_genesis_config},
+        solana_runtime::{bank::Bank, bank_forks::BankForks, genesis_utils::create_genesis_config},
         solana_sdk::{
         solana_sdk::{
             account::AccountSharedData,
             account::AccountSharedData,
             address_lookup_table::{
             address_lookup_table::{
@@ -101,7 +101,10 @@ mod tests {
             signer::Signer,
             signer::Signer,
             transaction::{MessageHash, SanitizedTransaction, VersionedTransaction},
             transaction::{MessageHash, SanitizedTransaction, VersionedTransaction},
         },
         },
-        std::{borrow::Cow, sync::Arc},
+        std::{
+            borrow::Cow,
+            sync::{Arc, RwLock},
+        },
     };
     };
 
 
     fn create_test_versioned_message(
     fn create_test_versioned_message(
@@ -171,9 +174,9 @@ mod tests {
         )
         )
     }
     }
 
 
-    fn create_test_bank() -> Arc<Bank> {
+    fn create_test_bank() -> (Arc<Bank>, Arc<RwLock<BankForks>>) {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
-        Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0
+        Bank::new_no_wallclock_throttle_for_tests(&genesis_config)
     }
     }
 
 
     // Helper function (could potentially use test_case in future).
     // Helper function (could potentially use test_case in future).
@@ -182,7 +185,7 @@ mod tests {
     // conflict_index = 2 means write lock conflict with address table key
     // conflict_index = 2 means write lock conflict with address table key
     // conflict_index = 3 means read lock conflict with address table key
     // conflict_index = 3 means read lock conflict with address table key
     fn test_check_and_take_locks(conflict_index: usize, add_write: bool, expectation: bool) {
     fn test_check_and_take_locks(conflict_index: usize, add_write: bool, expectation: bool) {
-        let bank = create_test_bank();
+        let (bank, _bank_forks) = create_test_bank();
         let (bank, table_address) = create_test_address_lookup_table(bank, 2);
         let (bank, table_address) = create_test_address_lookup_table(bank, 2);
         let tx = create_test_sanitized_transaction(
         let tx = create_test_sanitized_transaction(
             &Keypair::new(),
             &Keypair::new(),

+ 1 - 1
core/src/banking_stage/unprocessed_transaction_storage.rs

@@ -1069,7 +1069,7 @@ mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(10);
         } = create_genesis_config(10);
-        let current_bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (current_bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
         let simple_transactions: Vec<Transaction> = (0..256)
         let simple_transactions: Vec<Transaction> = (0..256)
             .map(|_id| {
             .map(|_id| {

+ 1 - 1
core/tests/unified_scheduler.rs

@@ -83,7 +83,7 @@ fn test_scheduler_waited_by_drop_bank_service() {
     bank_forks.write().unwrap().install_scheduler_pool(pool);
     bank_forks.write().unwrap().install_scheduler_pool(pool);
     let genesis = 0;
     let genesis = 0;
     let genesis_bank = &bank_forks.read().unwrap().get(genesis).unwrap();
     let genesis_bank = &bank_forks.read().unwrap().get(genesis).unwrap();
-    genesis_bank.set_fork_graph_in_program_cache(bank_forks.clone());
+    genesis_bank.set_fork_graph_in_program_cache(Arc::downgrade(&bank_forks));
 
 
     // Create bank, which is pruned later
     // Create bank, which is pruned later
     let pruned = 2;
     let pruned = 2;

+ 9 - 3
ledger/benches/blockstore_processor.rs

@@ -12,7 +12,7 @@ use {
     },
     },
     solana_program_runtime::timings::ExecuteTimings,
     solana_program_runtime::timings::ExecuteTimings,
     solana_runtime::{
     solana_runtime::{
-        bank::Bank, prioritization_fee_cache::PrioritizationFeeCache,
+        bank::Bank, bank_forks::BankForks, prioritization_fee_cache::PrioritizationFeeCache,
         transaction_batch::TransactionBatch,
         transaction_batch::TransactionBatch,
     },
     },
     solana_sdk::{
     solana_sdk::{
@@ -24,7 +24,10 @@ use {
         system_program, system_transaction,
         system_program, system_transaction,
         transaction::SanitizedTransaction,
         transaction::SanitizedTransaction,
     },
     },
-    std::{borrow::Cow, sync::Arc},
+    std::{
+        borrow::Cow,
+        sync::{Arc, RwLock},
+    },
     test::Bencher,
     test::Bencher,
 };
 };
 
 
@@ -74,6 +77,7 @@ fn create_transactions(bank: &Bank, num: usize) -> Vec<SanitizedTransaction> {
 
 
 struct BenchFrame {
 struct BenchFrame {
     bank: Arc<Bank>,
     bank: Arc<Bank>,
+    _bank_forks: Arc<RwLock<BankForks>>,
     prioritization_fee_cache: PrioritizationFeeCache,
     prioritization_fee_cache: PrioritizationFeeCache,
 }
 }
 
 
@@ -100,10 +104,11 @@ fn setup(apply_cost_tracker_during_replay: bool) -> BenchFrame {
     bank.write_cost_tracker()
     bank.write_cost_tracker()
         .unwrap()
         .unwrap()
         .set_limits(u64::MAX, u64::MAX, u64::MAX);
         .set_limits(u64::MAX, u64::MAX, u64::MAX);
-    let bank = bank.wrap_with_bank_forks_for_tests().0;
+    let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
     let prioritization_fee_cache = PrioritizationFeeCache::default();
     let prioritization_fee_cache = PrioritizationFeeCache::default();
     BenchFrame {
     BenchFrame {
         bank,
         bank,
+        _bank_forks: bank_forks,
         prioritization_fee_cache,
         prioritization_fee_cache,
     }
     }
 }
 }
@@ -124,6 +129,7 @@ fn bench_execute_batch(
 
 
     let BenchFrame {
     let BenchFrame {
         bank,
         bank,
+        _bank_forks,
         prioritization_fee_cache,
         prioritization_fee_cache,
     } = setup(apply_cost_tracker_during_replay);
     } = setup(apply_cost_tracker_during_replay);
     let transactions = create_transactions(&bank, 2_usize.pow(20));
     let transactions = create_transactions(&bank, 2_usize.pow(20));

+ 19 - 22
ledger/src/blockstore_processor.rs

@@ -3007,7 +3007,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(2);
         } = create_genesis_config(2);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let keypair = Keypair::new();
         let keypair = Keypair::new();
         let slot_entries = create_ticks(genesis_config.ticks_per_slot, 1, genesis_config.hash());
         let slot_entries = create_ticks(genesis_config.ticks_per_slot, 1, genesis_config.hash());
         let tx = system_transaction::transfer(
         let tx = system_transaction::transfer(
@@ -3172,7 +3172,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(1000);
         } = create_genesis_config(1000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let keypair1 = Keypair::new();
         let keypair1 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair2 = Keypair::new();
 
 
@@ -3209,7 +3209,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(1000);
         } = create_genesis_config(1000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let keypair1 = Keypair::new();
         let keypair1 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair3 = Keypair::new();
         let keypair3 = Keypair::new();
@@ -3269,7 +3269,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(1000);
         } = create_genesis_config(1000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let keypair1 = Keypair::new();
         let keypair1 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair3 = Keypair::new();
         let keypair3 = Keypair::new();
@@ -3419,12 +3419,11 @@ pub mod tests {
 
 
         let mock_program_id = solana_sdk::pubkey::new_rand();
         let mock_program_id = solana_sdk::pubkey::new_rand();
 
 
-        let bank = Bank::new_with_mockup_builtin_for_tests(
+        let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
             &genesis_config,
             &genesis_config,
             mock_program_id,
             mock_program_id,
             MockBuiltinOk::vm,
             MockBuiltinOk::vm,
-        )
-        .0;
+        );
 
 
         let tx = Transaction::new_signed_with_payer(
         let tx = Transaction::new_signed_with_payer(
             &[Instruction::new_with_bincode(
             &[Instruction::new_with_bincode(
@@ -3463,12 +3462,11 @@ pub mod tests {
         let mut bankhash_err = None;
         let mut bankhash_err = None;
 
 
         (0..get_instruction_errors().len()).for_each(|err| {
         (0..get_instruction_errors().len()).for_each(|err| {
-            let bank = Bank::new_with_mockup_builtin_for_tests(
+            let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
                 &genesis_config,
                 &genesis_config,
                 mock_program_id,
                 mock_program_id,
                 MockBuiltinErr::vm,
                 MockBuiltinErr::vm,
-            )
-            .0;
+            );
 
 
             let tx = Transaction::new_signed_with_payer(
             let tx = Transaction::new_signed_with_payer(
                 &[Instruction::new_with_bincode(
                 &[Instruction::new_with_bincode(
@@ -3504,7 +3502,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(1000);
         } = create_genesis_config(1000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let keypair1 = Keypair::new();
         let keypair1 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair3 = Keypair::new();
         let keypair3 = Keypair::new();
@@ -3598,7 +3596,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(1000);
         } = create_genesis_config(1000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let keypair1 = Keypair::new();
         let keypair1 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair3 = Keypair::new();
         let keypair3 = Keypair::new();
@@ -3644,7 +3642,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(1_000_000_000);
         } = create_genesis_config(1_000_000_000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
         const NUM_TRANSFERS_PER_ENTRY: usize = 8;
         const NUM_TRANSFERS_PER_ENTRY: usize = 8;
         const NUM_TRANSFERS: usize = NUM_TRANSFERS_PER_ENTRY * 32;
         const NUM_TRANSFERS: usize = NUM_TRANSFERS_PER_ENTRY * 32;
@@ -3711,7 +3709,7 @@ pub mod tests {
             ..
             ..
         } = create_genesis_config((num_accounts + 1) as u64 * initial_lamports);
         } = create_genesis_config((num_accounts + 1) as u64 * initial_lamports);
 
 
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
         let mut keypairs: Vec<Keypair> = vec![];
         let mut keypairs: Vec<Keypair> = vec![];
 
 
@@ -3778,7 +3776,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(1000);
         } = create_genesis_config(1000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let keypair1 = Keypair::new();
         let keypair1 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair3 = Keypair::new();
         let keypair3 = Keypair::new();
@@ -3840,7 +3838,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(11_000);
         } = create_genesis_config(11_000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let pubkey = solana_sdk::pubkey::new_rand();
         let pubkey = solana_sdk::pubkey::new_rand();
         bank.transfer(1_000, &mint_keypair, &pubkey).unwrap();
         bank.transfer(1_000, &mint_keypair, &pubkey).unwrap();
         assert_eq!(bank.transaction_count(), 1);
         assert_eq!(bank.transaction_count(), 1);
@@ -3881,7 +3879,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(11_000);
         } = create_genesis_config(11_000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let keypair1 = Keypair::new();
         let keypair1 = Keypair::new();
         let keypair2 = Keypair::new();
         let keypair2 = Keypair::new();
         let success_tx = system_transaction::transfer(
         let success_tx = system_transaction::transfer(
@@ -4181,7 +4179,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(100);
         } = create_genesis_config(100);
-        let bank0 = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank0, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let genesis_hash = genesis_config.hash();
         let genesis_hash = genesis_config.hash();
         let keypair = Keypair::new();
         let keypair = Keypair::new();
 
 
@@ -4245,7 +4243,7 @@ pub mod tests {
             mint_keypair,
             mint_keypair,
             ..
             ..
         } = create_genesis_config(1_000_000_000);
         } = create_genesis_config(1_000_000_000);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
         let present_account_key = Keypair::new();
         let present_account_key = Keypair::new();
         let present_account = AccountSharedData::new(1, 10, &Pubkey::default());
         let present_account = AccountSharedData::new(1, 10, &Pubkey::default());
@@ -4714,9 +4712,8 @@ pub mod tests {
             ..
             ..
         } = create_genesis_config(100 * LAMPORTS_PER_SOL);
         } = create_genesis_config(100 * LAMPORTS_PER_SOL);
         let genesis_hash = genesis_config.hash();
         let genesis_hash = genesis_config.hash();
-        let bank = BankWithScheduler::new_without_scheduler(
-            Bank::new_with_bank_forks_for_tests(&genesis_config).0,
-        );
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
+        let bank = BankWithScheduler::new_without_scheduler(bank);
         let replay_tx_thread_pool = create_thread_pool(1);
         let replay_tx_thread_pool = create_thread_pool(1);
         let mut timing = ConfirmationTiming::default();
         let mut timing = ConfirmationTiming::default();
         let mut progress = ConfirmationProgress::new(genesis_hash);
         let mut progress = ConfirmationProgress::new(genesis_hash);

+ 1 - 1
poh/src/poh_service.rs

@@ -400,7 +400,7 @@ mod tests {
     fn test_poh_service() {
     fn test_poh_service() {
         solana_logger::setup();
         solana_logger::setup();
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(2);
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(2);
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
         let prev_hash = bank.last_blockhash();
         let prev_hash = bank.last_blockhash();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let blockstore = Blockstore::open(ledger_path.path())
         let blockstore = Blockstore::open(ledger_path.path())

+ 21 - 15
program-runtime/src/loaded_programs.rs

@@ -30,6 +30,7 @@ use {
     std::{
     std::{
         collections::{hash_map::Entry, HashMap},
         collections::{hash_map::Entry, HashMap},
         fmt::{Debug, Formatter},
         fmt::{Debug, Formatter},
+        sync::Weak,
     },
     },
 };
 };
 
 
@@ -640,7 +641,7 @@ pub struct ProgramCache<FG: ForkGraph> {
     /// Statistics counters
     /// Statistics counters
     pub stats: ProgramCacheStats,
     pub stats: ProgramCacheStats,
     /// Reference to the block store
     /// Reference to the block store
-    pub fork_graph: Option<Arc<RwLock<FG>>>,
+    pub fork_graph: Option<Weak<RwLock<FG>>>,
     /// Coordinates TX batches waiting for others to complete their task during cooperative loading
     /// Coordinates TX batches waiting for others to complete their task during cooperative loading
     pub loading_task_waiter: Arc<LoadingTaskWaiter>,
     pub loading_task_waiter: Arc<LoadingTaskWaiter>,
 }
 }
@@ -825,7 +826,7 @@ impl<FG: ForkGraph> ProgramCache<FG> {
         }
         }
     }
     }
 
 
-    pub fn set_fork_graph(&mut self, fork_graph: Arc<RwLock<FG>>) {
+    pub fn set_fork_graph(&mut self, fork_graph: Weak<RwLock<FG>>) {
         self.fork_graph = Some(fork_graph);
         self.fork_graph = Some(fork_graph);
     }
     }
 
 
@@ -948,6 +949,7 @@ impl<FG: ForkGraph> ProgramCache<FG> {
             error!("Program cache doesn't have fork graph.");
             error!("Program cache doesn't have fork graph.");
             return;
             return;
         };
         };
+        let fork_graph = fork_graph.upgrade().unwrap();
         let Ok(fork_graph) = fork_graph.read() else {
         let Ok(fork_graph) = fork_graph.read() else {
             error!("Failed to lock fork graph for reading.");
             error!("Failed to lock fork graph for reading.");
             return;
             return;
@@ -1059,7 +1061,8 @@ impl<FG: ForkGraph> ProgramCache<FG> {
         is_first_round: bool,
         is_first_round: bool,
     ) -> Option<(Pubkey, u64)> {
     ) -> Option<(Pubkey, u64)> {
         debug_assert!(self.fork_graph.is_some());
         debug_assert!(self.fork_graph.is_some());
-        let locked_fork_graph = self.fork_graph.as_ref().unwrap().read().unwrap();
+        let fork_graph = self.fork_graph.as_ref().unwrap().upgrade().unwrap();
+        let locked_fork_graph = fork_graph.read().unwrap();
         let mut cooperative_loading_task = None;
         let mut cooperative_loading_task = None;
         match &self.index {
         match &self.index {
             IndexImplementation::V1 {
             IndexImplementation::V1 {
@@ -1166,6 +1169,8 @@ impl<FG: ForkGraph> ProgramCache<FG> {
                         self.fork_graph
                         self.fork_graph
                             .as_ref()
                             .as_ref()
                             .unwrap()
                             .unwrap()
+                            .upgrade()
+                            .unwrap()
                             .read()
                             .read()
                             .unwrap()
                             .unwrap()
                             .relationship(loaded_program.deployment_slot, slot),
                             .relationship(loaded_program.deployment_slot, slot),
@@ -2026,7 +2031,7 @@ mod tests {
             relation: BlockRelation::Unrelated,
             relation: BlockRelation::Unrelated,
         }));
         }));
 
 
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         cache.prune(0, 0);
         cache.prune(0, 0);
         assert!(cache.get_flattened_entries_for_tests().is_empty());
         assert!(cache.get_flattened_entries_for_tests().is_empty());
@@ -2039,7 +2044,7 @@ mod tests {
             relation: BlockRelation::Ancestor,
             relation: BlockRelation::Ancestor,
         }));
         }));
 
 
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         cache.prune(0, 0);
         cache.prune(0, 0);
         assert!(cache.get_flattened_entries_for_tests().is_empty());
         assert!(cache.get_flattened_entries_for_tests().is_empty());
@@ -2052,7 +2057,7 @@ mod tests {
             relation: BlockRelation::Descendant,
             relation: BlockRelation::Descendant,
         }));
         }));
 
 
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         cache.prune(0, 0);
         cache.prune(0, 0);
         assert!(cache.get_flattened_entries_for_tests().is_empty());
         assert!(cache.get_flattened_entries_for_tests().is_empty());
@@ -2064,7 +2069,7 @@ mod tests {
         let fork_graph = Arc::new(RwLock::new(TestForkGraph {
         let fork_graph = Arc::new(RwLock::new(TestForkGraph {
             relation: BlockRelation::Unknown,
             relation: BlockRelation::Unknown,
         }));
         }));
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         cache.prune(0, 0);
         cache.prune(0, 0);
         assert!(cache.get_flattened_entries_for_tests().is_empty());
         assert!(cache.get_flattened_entries_for_tests().is_empty());
@@ -2081,7 +2086,7 @@ mod tests {
             relation: BlockRelation::Ancestor,
             relation: BlockRelation::Ancestor,
         }));
         }));
 
 
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         let program1 = Pubkey::new_unique();
         let program1 = Pubkey::new_unique();
         cache.assign_program(program1, new_test_entry(10, 10));
         cache.assign_program(program1, new_test_entry(10, 10));
@@ -2171,7 +2176,8 @@ mod tests {
         loading_slot: Slot,
         loading_slot: Slot,
         keys: &[Pubkey],
         keys: &[Pubkey],
     ) -> Vec<(Pubkey, (ProgramCacheMatchCriteria, u64))> {
     ) -> Vec<(Pubkey, (ProgramCacheMatchCriteria, u64))> {
-        let locked_fork_graph = cache.fork_graph.as_ref().unwrap().read().unwrap();
+        let fork_graph = cache.fork_graph.as_ref().unwrap().upgrade().unwrap();
+        let locked_fork_graph = fork_graph.read().unwrap();
         let entries = cache.get_flattened_entries_for_tests();
         let entries = cache.get_flattened_entries_for_tests();
         keys.iter()
         keys.iter()
             .filter_map(|key| {
             .filter_map(|key| {
@@ -2239,7 +2245,7 @@ mod tests {
         fork_graph.insert_fork(&[0, 5, 11, 25, 27]);
         fork_graph.insert_fork(&[0, 5, 11, 25, 27]);
 
 
         let fork_graph = Arc::new(RwLock::new(fork_graph));
         let fork_graph = Arc::new(RwLock::new(fork_graph));
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         let program1 = Pubkey::new_unique();
         let program1 = Pubkey::new_unique();
         cache.assign_program(program1, new_test_entry(0, 1));
         cache.assign_program(program1, new_test_entry(0, 1));
@@ -2434,7 +2440,7 @@ mod tests {
         fork_graph.insert_fork(&[0, 5, 11, 25, 27]);
         fork_graph.insert_fork(&[0, 5, 11, 25, 27]);
 
 
         let fork_graph = Arc::new(RwLock::new(fork_graph));
         let fork_graph = Arc::new(RwLock::new(fork_graph));
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         let program1 = Pubkey::new_unique();
         let program1 = Pubkey::new_unique();
         cache.assign_program(program1, new_test_entry(0, 1));
         cache.assign_program(program1, new_test_entry(0, 1));
@@ -2491,7 +2497,7 @@ mod tests {
         fork_graph.insert_fork(&[0, 5, 11, 25, 27]);
         fork_graph.insert_fork(&[0, 5, 11, 25, 27]);
 
 
         let fork_graph = Arc::new(RwLock::new(fork_graph));
         let fork_graph = Arc::new(RwLock::new(fork_graph));
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         let program1 = Pubkey::new_unique();
         let program1 = Pubkey::new_unique();
         cache.assign_program(program1, new_test_entry(0, 1));
         cache.assign_program(program1, new_test_entry(0, 1));
@@ -2547,7 +2553,7 @@ mod tests {
         let mut cache = new_mock_cache::<TestForkGraphSpecific>();
         let mut cache = new_mock_cache::<TestForkGraphSpecific>();
         let fork_graph = TestForkGraphSpecific::default();
         let fork_graph = TestForkGraphSpecific::default();
         let fork_graph = Arc::new(RwLock::new(fork_graph));
         let fork_graph = Arc::new(RwLock::new(fork_graph));
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         let program1 = Pubkey::new_unique();
         let program1 = Pubkey::new_unique();
         let mut missing = vec![(program1, (ProgramCacheMatchCriteria::NoCriteria, 1))];
         let mut missing = vec![(program1, (ProgramCacheMatchCriteria::NoCriteria, 1))];
@@ -2619,7 +2625,7 @@ mod tests {
         fork_graph.insert_fork(&[0, 10, 20]);
         fork_graph.insert_fork(&[0, 10, 20]);
         fork_graph.insert_fork(&[0, 5]);
         fork_graph.insert_fork(&[0, 5]);
         let fork_graph = Arc::new(RwLock::new(fork_graph));
         let fork_graph = Arc::new(RwLock::new(fork_graph));
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         let program1 = Pubkey::new_unique();
         let program1 = Pubkey::new_unique();
         cache.assign_program(program1, new_test_entry(0, 1));
         cache.assign_program(program1, new_test_entry(0, 1));
@@ -2659,7 +2665,7 @@ mod tests {
         fork_graph.insert_fork(&[0, 10, 20]);
         fork_graph.insert_fork(&[0, 10, 20]);
         fork_graph.insert_fork(&[0, 5, 6]);
         fork_graph.insert_fork(&[0, 5, 6]);
         let fork_graph = Arc::new(RwLock::new(fork_graph));
         let fork_graph = Arc::new(RwLock::new(fork_graph));
-        cache.set_fork_graph(fork_graph);
+        cache.set_fork_graph(Arc::downgrade(&fork_graph));
 
 
         let program1 = Pubkey::new_unique();
         let program1 = Pubkey::new_unique();
         cache.assign_program(program1, new_test_entry(0, 1));
         cache.assign_program(program1, new_test_entry(0, 1));

+ 11 - 5
programs/sbf/tests/programs.rs

@@ -23,6 +23,7 @@ use {
     solana_runtime::{
     solana_runtime::{
         bank::{Bank, TransactionBalancesSet},
         bank::{Bank, TransactionBalancesSet},
         bank_client::BankClient,
         bank_client::BankClient,
+        bank_forks::BankForks,
         genesis_utils::{
         genesis_utils::{
             bootstrap_validator_stake_lamports, create_genesis_config,
             bootstrap_validator_stake_lamports, create_genesis_config,
             create_genesis_config_with_leader_ex, GenesisConfigInfo,
             create_genesis_config_with_leader_ex, GenesisConfigInfo,
@@ -73,7 +74,12 @@ use {
         TransactionWithStatusMeta, VersionedTransactionWithStatusMeta,
         TransactionWithStatusMeta, VersionedTransactionWithStatusMeta,
     },
     },
     std::{
     std::{
-        assert_eq, cell::RefCell, collections::HashMap, str::FromStr, sync::Arc, time::Duration,
+        assert_eq,
+        cell::RefCell,
+        collections::HashMap,
+        str::FromStr,
+        sync::{Arc, RwLock},
+        time::Duration,
     },
     },
 };
 };
 
 
@@ -2530,7 +2536,7 @@ fn test_program_upgradeable_locks() {
         payer_keypair: &Keypair,
         payer_keypair: &Keypair,
         buffer_keypair: &Keypair,
         buffer_keypair: &Keypair,
         program_keypair: &Keypair,
         program_keypair: &Keypair,
-    ) -> (Arc<Bank>, Transaction, Transaction) {
+    ) -> (Arc<Bank>, Arc<RwLock<BankForks>>, Transaction, Transaction) {
         solana_logger::setup();
         solana_logger::setup();
 
 
         let GenesisConfigInfo {
         let GenesisConfigInfo {
@@ -2600,7 +2606,7 @@ fn test_program_upgradeable_locks() {
             bank.last_blockhash(),
             bank.last_blockhash(),
         );
         );
 
 
-        (bank, invoke_tx, upgrade_tx)
+        (bank, bank_forks, invoke_tx, upgrade_tx)
     }
     }
 
 
     let payer_keypair = keypair_from_seed(&[56u8; 32]).unwrap();
     let payer_keypair = keypair_from_seed(&[56u8; 32]).unwrap();
@@ -2608,13 +2614,13 @@ fn test_program_upgradeable_locks() {
     let program_keypair = keypair_from_seed(&[77u8; 32]).unwrap();
     let program_keypair = keypair_from_seed(&[77u8; 32]).unwrap();
 
 
     let results1 = {
     let results1 = {
-        let (bank, invoke_tx, upgrade_tx) =
+        let (bank, _bank_forks, invoke_tx, upgrade_tx) =
             setup_program_upgradeable_locks(&payer_keypair, &buffer_keypair, &program_keypair);
             setup_program_upgradeable_locks(&payer_keypair, &buffer_keypair, &program_keypair);
         execute_transactions(&bank, vec![upgrade_tx, invoke_tx])
         execute_transactions(&bank, vec![upgrade_tx, invoke_tx])
     };
     };
 
 
     let results2 = {
     let results2 = {
-        let (bank, invoke_tx, upgrade_tx) =
+        let (bank, _bank_forks, invoke_tx, upgrade_tx) =
             setup_program_upgradeable_locks(&payer_keypair, &buffer_keypair, &program_keypair);
             setup_program_upgradeable_locks(&payer_keypair, &buffer_keypair, &program_keypair);
         execute_transactions(&bank, vec![invoke_tx, upgrade_tx])
         execute_transactions(&bank, vec![invoke_tx, upgrade_tx])
     };
     };

+ 1 - 1
rpc/src/transaction_status_service.rs

@@ -291,7 +291,7 @@ pub(crate) mod tests {
     #[test]
     #[test]
     fn test_notify_transaction() {
     fn test_notify_transaction() {
         let genesis_config = create_genesis_config(2).genesis_config;
         let genesis_config = create_genesis_config(2).genesis_config;
-        let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
 
 
         let (transaction_status_sender, transaction_status_receiver) = unbounded();
         let (transaction_status_sender, transaction_status_receiver) = unbounded();
         let ledger_path = get_tmp_ledger_path_auto_delete!();
         let ledger_path = get_tmp_ledger_path_auto_delete!();

+ 2 - 2
runtime/src/bank.rs

@@ -190,7 +190,7 @@ use {
                 AtomicBool, AtomicI64, AtomicU64, AtomicUsize,
                 AtomicBool, AtomicI64, AtomicU64, AtomicUsize,
                 Ordering::{AcqRel, Acquire, Relaxed},
                 Ordering::{AcqRel, Acquire, Relaxed},
             },
             },
-            Arc, LockResult, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard,
+            Arc, LockResult, Mutex, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak,
         },
         },
         thread::Builder,
         thread::Builder,
         time::{Duration, Instant},
         time::{Duration, Instant},
@@ -1351,7 +1351,7 @@ impl Bank {
         new
         new
     }
     }
 
 
-    pub fn set_fork_graph_in_program_cache(&self, fork_graph: Arc<RwLock<BankForks>>) {
+    pub fn set_fork_graph_in_program_cache(&self, fork_graph: Weak<RwLock<BankForks>>) {
         self.transaction_processor
         self.transaction_processor
             .program_cache
             .program_cache
             .write()
             .write()

+ 91 - 114
runtime/src/bank/tests.rs

@@ -318,7 +318,7 @@ fn create_simple_test_arc_bank(lamports: u64) -> (Arc<Bank>, Arc<RwLock<BankFork
 
 
 #[test]
 #[test]
 fn test_bank_block_height() {
 fn test_bank_block_height() {
-    let bank0 = create_simple_test_arc_bank(1).0;
+    let (bank0, _bank_forks) = create_simple_test_arc_bank(1);
     assert_eq!(bank0.block_height(), 0);
     assert_eq!(bank0.block_height(), 0);
     let bank1 = Arc::new(new_from_parent(bank0));
     let bank1 = Arc::new(new_from_parent(bank0));
     assert_eq!(bank1.block_height(), 1);
     assert_eq!(bank1.block_height(), 1);
@@ -922,7 +922,7 @@ fn test_rent_distribution() {
     // Enable rent collection
     // Enable rent collection
     bank.rent_collector.epoch = 5;
     bank.rent_collector.epoch = 5;
     bank.rent_collector.slots_per_year = 192.0;
     bank.rent_collector.slots_per_year = 192.0;
-    let bank = bank.wrap_with_bank_forks_for_tests().0;
+    let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests();
 
 
     let payer = Keypair::new();
     let payer = Keypair::new();
     let payer_account = AccountSharedData::new(400, 0, &system_program::id());
     let payer_account = AccountSharedData::new(400, 0, &system_program::id());
@@ -1271,7 +1271,7 @@ fn test_rent_complex() {
 
 
 #[test]
 #[test]
 fn test_rent_eager_across_epoch_without_gap() {
 fn test_rent_eager_across_epoch_without_gap() {
-    let mut bank = create_simple_test_arc_bank(1).0;
+    let (mut bank, _bank_forks) = create_simple_test_arc_bank(1);
     assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
     assert_eq!(bank.rent_collection_partitions(), vec![(0, 0, 32)]);
 
 
     bank = Arc::new(new_from_parent(bank));
     bank = Arc::new(new_from_parent(bank));
@@ -2217,7 +2217,7 @@ fn test_purge_empty_accounts() {
 fn test_two_payments_to_one_party() {
 fn test_two_payments_to_one_party() {
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let pubkey = solana_sdk::pubkey::new_rand();
     let pubkey = solana_sdk::pubkey::new_rand();
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
     assert_eq!(bank.last_blockhash(), genesis_config.hash());
     assert_eq!(bank.last_blockhash(), genesis_config.hash());
 
 
@@ -2235,7 +2235,7 @@ fn test_one_source_two_tx_one_batch() {
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.));
     let key1 = solana_sdk::pubkey::new_rand();
     let key1 = solana_sdk::pubkey::new_rand();
     let key2 = solana_sdk::pubkey::new_rand();
     let key2 = solana_sdk::pubkey::new_rand();
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
     assert_eq!(bank.last_blockhash(), genesis_config.hash());
     assert_eq!(bank.last_blockhash(), genesis_config.hash());
 
 
@@ -2265,7 +2265,7 @@ fn test_one_tx_two_out_atomic_fail() {
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee_no_rent(amount);
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee_no_rent(amount);
     let key1 = solana_sdk::pubkey::new_rand();
     let key1 = solana_sdk::pubkey::new_rand();
     let key2 = solana_sdk::pubkey::new_rand();
     let key2 = solana_sdk::pubkey::new_rand();
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let instructions = system_instruction::transfer_many(
     let instructions = system_instruction::transfer_many(
         &mint_keypair.pubkey(),
         &mint_keypair.pubkey(),
         &[(key1, amount), (key2, amount)],
         &[(key1, amount), (key2, amount)],
@@ -2286,7 +2286,7 @@ fn test_one_tx_two_out_atomic_pass() {
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.));
     let key1 = solana_sdk::pubkey::new_rand();
     let key1 = solana_sdk::pubkey::new_rand();
     let key2 = solana_sdk::pubkey::new_rand();
     let key2 = solana_sdk::pubkey::new_rand();
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
     let instructions = system_instruction::transfer_many(
     let instructions = system_instruction::transfer_many(
         &mint_keypair.pubkey(),
         &mint_keypair.pubkey(),
@@ -2308,7 +2308,7 @@ fn test_one_tx_two_out_atomic_pass() {
 fn test_detect_failed_duplicate_transactions() {
 fn test_detect_failed_duplicate_transactions() {
     let (mut genesis_config, mint_keypair) = create_genesis_config(10_000);
     let (mut genesis_config, mint_keypair) = create_genesis_config(10_000);
     genesis_config.fee_rate_governor = FeeRateGovernor::new(5_000, 0);
     genesis_config.fee_rate_governor = FeeRateGovernor::new(5_000, 0);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     let dest = Keypair::new();
     let dest = Keypair::new();
 
 
@@ -2337,7 +2337,7 @@ fn test_detect_failed_duplicate_transactions() {
 fn test_account_not_found() {
 fn test_account_not_found() {
     solana_logger::setup();
     solana_logger::setup();
     let (genesis_config, mint_keypair) = create_genesis_config(0);
     let (genesis_config, mint_keypair) = create_genesis_config(0);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let keypair = Keypair::new();
     let keypair = Keypair::new();
     assert_eq!(
     assert_eq!(
         bank.transfer(
         bank.transfer(
@@ -2355,7 +2355,7 @@ fn test_account_not_found() {
 fn test_insufficient_funds() {
 fn test_insufficient_funds() {
     let mint_amount = sol_to_lamports(1.);
     let mint_amount = sol_to_lamports(1.);
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(mint_amount);
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(mint_amount);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let pubkey = solana_sdk::pubkey::new_rand();
     let pubkey = solana_sdk::pubkey::new_rand();
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
     bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
     bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
@@ -2426,7 +2426,7 @@ fn test_executed_transaction_count_post_bank_transaction_count_fix() {
 fn test_transfer_to_newb() {
 fn test_transfer_to_newb() {
     solana_logger::setup();
     solana_logger::setup();
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
     let pubkey = solana_sdk::pubkey::new_rand();
     let pubkey = solana_sdk::pubkey::new_rand();
     bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
     bank.transfer(amount, &mint_keypair, &pubkey).unwrap();
@@ -2926,7 +2926,7 @@ fn test_filter_program_errors_and_collect_priority_fee() {
 fn test_debits_before_credits() {
 fn test_debits_before_credits() {
     let (genesis_config, mint_keypair) =
     let (genesis_config, mint_keypair) =
         create_genesis_config_no_tx_fee_no_rent(sol_to_lamports(2.));
         create_genesis_config_no_tx_fee_no_rent(sol_to_lamports(2.));
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let keypair = Keypair::new();
     let keypair = Keypair::new();
     let tx0 = system_transaction::transfer(
     let tx0 = system_transaction::transfer(
         &mint_keypair,
         &mint_keypair,
@@ -2956,7 +2956,7 @@ fn test_readonly_accounts() {
         mint_keypair,
         mint_keypair,
         ..
         ..
     } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 0);
     } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 0);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     let vote_pubkey0 = solana_sdk::pubkey::new_rand();
     let vote_pubkey0 = solana_sdk::pubkey::new_rand();
     let vote_pubkey1 = solana_sdk::pubkey::new_rand();
     let vote_pubkey1 = solana_sdk::pubkey::new_rand();
@@ -3028,7 +3028,7 @@ fn test_readonly_accounts() {
 #[test]
 #[test]
 fn test_interleaving_locks() {
 fn test_interleaving_locks() {
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let alice = Keypair::new();
     let alice = Keypair::new();
     let bob = Keypair::new();
     let bob = Keypair::new();
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
@@ -3163,7 +3163,7 @@ fn test_bank_invalid_account_index() {
 fn test_bank_pay_to_self() {
 fn test_bank_pay_to_self() {
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.));
     let key1 = Keypair::new();
     let key1 = Keypair::new();
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
 
 
     bank.transfer(amount, &mint_keypair, &key1.pubkey())
     bank.transfer(amount, &mint_keypair, &key1.pubkey())
@@ -3203,7 +3203,7 @@ fn test_bank_parents() {
 #[test]
 #[test]
 fn test_tx_already_processed() {
 fn test_tx_already_processed() {
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     let key1 = Keypair::new();
     let key1 = Keypair::new();
     let mut tx = system_transaction::transfer(
     let mut tx = system_transaction::transfer(
@@ -3273,7 +3273,7 @@ fn test_bank_parent_account_spend() {
 fn test_bank_hash_internal_state() {
 fn test_bank_hash_internal_state() {
     let (genesis_config, mint_keypair) =
     let (genesis_config, mint_keypair) =
         create_genesis_config_no_tx_fee_no_rent(sol_to_lamports(1.));
         create_genesis_config_no_tx_fee_no_rent(sol_to_lamports(1.));
-    let (bank0, _) = Bank::new_with_bank_forks_for_tests(&genesis_config);
+    let (bank0, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let (bank1, bank_forks_1) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let (bank1, bank_forks_1) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
     let initial_state = bank0.hash_internal_state();
     let initial_state = bank0.hash_internal_state();
@@ -3379,7 +3379,7 @@ fn test_verify_snapshot_bank() {
     solana_logger::setup();
     solana_logger::setup();
     let pubkey = solana_sdk::pubkey::new_rand();
     let pubkey = solana_sdk::pubkey::new_rand();
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     bank.transfer(
     bank.transfer(
         genesis_config.rent.minimum_balance(0),
         genesis_config.rent.minimum_balance(0),
         &mint_keypair,
         &mint_keypair,
@@ -3439,8 +3439,8 @@ fn test_hash_internal_state_genesis() {
 fn test_hash_internal_state_order() {
 fn test_hash_internal_state_order() {
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
-    let bank0 = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
-    let bank1 = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank0, _bank_forks0) = Bank::new_with_bank_forks_for_tests(&genesis_config);
+    let (bank1, _bank_forks1) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
     assert_eq!(bank0.hash_internal_state(), bank1.hash_internal_state());
     let key0 = solana_sdk::pubkey::new_rand();
     let key0 = solana_sdk::pubkey::new_rand();
     let key1 = solana_sdk::pubkey::new_rand();
     let key1 = solana_sdk::pubkey::new_rand();
@@ -3458,7 +3458,7 @@ fn test_hash_internal_state_error() {
     solana_logger::setup();
     solana_logger::setup();
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let key0 = solana_sdk::pubkey::new_rand();
     let key0 = solana_sdk::pubkey::new_rand();
     bank.transfer(amount, &mint_keypair, &key0).unwrap();
     bank.transfer(amount, &mint_keypair, &key0).unwrap();
     let orig = bank.hash_internal_state();
     let orig = bank.hash_internal_state();
@@ -3569,7 +3569,7 @@ fn test_bank_squash() {
 #[test]
 #[test]
 fn test_bank_get_account_in_parent_after_squash() {
 fn test_bank_get_account_in_parent_after_squash() {
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.));
-    let parent = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (parent, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
 
 
     let key1 = Keypair::new();
     let key1 = Keypair::new();
@@ -4007,7 +4007,7 @@ fn test_bank_get_slots_in_epoch() {
 #[test]
 #[test]
 fn test_is_delta_true() {
 fn test_is_delta_true() {
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let key1 = Keypair::new();
     let key1 = Keypair::new();
     let tx_transfer_mint_to_1 = system_transaction::transfer(
     let tx_transfer_mint_to_1 = system_transaction::transfer(
         &mint_keypair,
         &mint_keypair,
@@ -4031,7 +4031,7 @@ fn test_is_delta_true() {
 #[test]
 #[test]
 fn test_is_empty() {
 fn test_is_empty() {
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
     let (genesis_config, mint_keypair) = create_genesis_config(sol_to_lamports(1.0));
-    let bank0 = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank0, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let key1 = Keypair::new();
     let key1 = Keypair::new();
 
 
     // The zeroth bank is empty becasue there are no transactions
     // The zeroth bank is empty becasue there are no transactions
@@ -4136,7 +4136,7 @@ fn test_bank_vote_accounts() {
         mint_keypair,
         mint_keypair,
         ..
         ..
     } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 1);
     } = create_genesis_config_with_leader(500, &solana_sdk::pubkey::new_rand(), 1);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     let vote_accounts = bank.vote_accounts();
     let vote_accounts = bank.vote_accounts();
     assert_eq!(vote_accounts.len(), 1); // bootstrap validator has
     assert_eq!(vote_accounts.len(), 1); // bootstrap validator has
@@ -4193,7 +4193,7 @@ fn test_bank_cloned_stake_delegations() {
         123_000_000_000,
         123_000_000_000,
     );
     );
     genesis_config.rent = Rent::default();
     genesis_config.rent = Rent::default();
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     let stake_delegations = bank.stakes_cache.stakes().stake_delegations().clone();
     let stake_delegations = bank.stakes_cache.stakes().stake_delegations().clone();
     assert_eq!(stake_delegations.len(), 1); // bootstrap validator has
     assert_eq!(stake_delegations.len(), 1); // bootstrap validator has
@@ -4254,7 +4254,7 @@ fn test_bank_cloned_stake_delegations() {
 #[test]
 #[test]
 fn test_is_delta_with_no_committables() {
 fn test_is_delta_with_no_committables() {
     let (genesis_config, mint_keypair) = create_genesis_config(8000);
     let (genesis_config, mint_keypair) = create_genesis_config(8000);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     bank.is_delta.store(false, Relaxed);
     bank.is_delta.store(false, Relaxed);
 
 
     let keypair1 = Keypair::new();
     let keypair1 = Keypair::new();
@@ -4470,7 +4470,7 @@ fn test_get_filtered_indexed_accounts() {
 #[test]
 #[test]
 fn test_status_cache_ancestors() {
 fn test_status_cache_ancestors() {
     solana_logger::setup();
     solana_logger::setup();
-    let parent = create_simple_test_arc_bank(500).0;
+    let (parent, _bank_forks) = create_simple_test_arc_bank(500);
     let bank1 = Arc::new(new_from_parent(parent));
     let bank1 = Arc::new(new_from_parent(parent));
     let mut bank = bank1;
     let mut bank = bank1;
     for _ in 0..MAX_CACHE_ENTRIES * 2 {
     for _ in 0..MAX_CACHE_ENTRIES * 2 {
@@ -4531,7 +4531,7 @@ fn test_add_builtin() {
         bank.last_blockhash(),
         bank.last_blockhash(),
     );
     );
 
 
-    let bank = bank.wrap_with_bank_forks_for_tests().0;
+    let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests();
     assert_eq!(
     assert_eq!(
         bank.process_transaction(&transaction),
         bank.process_transaction(&transaction),
         Err(TransactionError::InstructionError(
         Err(TransactionError::InstructionError(
@@ -4697,7 +4697,7 @@ fn test_add_instruction_processor_for_existing_unrelated_accounts() {
 #[allow(deprecated)]
 #[allow(deprecated)]
 #[test]
 #[test]
 fn test_recent_blockhashes_sysvar() {
 fn test_recent_blockhashes_sysvar() {
-    let mut bank = create_simple_test_arc_bank(500).0;
+    let (mut bank, _bank_forks) = create_simple_test_arc_bank(500);
     for i in 1..5 {
     for i in 1..5 {
         let bhq_account = bank.get_account(&sysvar::recent_blockhashes::id()).unwrap();
         let bhq_account = bank.get_account(&sysvar::recent_blockhashes::id()).unwrap();
         let recent_blockhashes =
         let recent_blockhashes =
@@ -4715,7 +4715,7 @@ fn test_recent_blockhashes_sysvar() {
 #[allow(deprecated)]
 #[allow(deprecated)]
 #[test]
 #[test]
 fn test_blockhash_queue_sysvar_consistency() {
 fn test_blockhash_queue_sysvar_consistency() {
-    let bank = create_simple_test_arc_bank(100_000).0;
+    let (bank, _bank_forks) = create_simple_test_arc_bank(100_000);
     goto_end_of_slot(bank.clone());
     goto_end_of_slot(bank.clone());
 
 
     let bhq_account = bank.get_account(&sysvar::recent_blockhashes::id()).unwrap();
     let bhq_account = bank.get_account(&sysvar::recent_blockhashes::id()).unwrap();
@@ -5067,7 +5067,7 @@ fn test_check_and_load_message_nonce_account_bad_tx_hash_fail() {
 
 
 #[test]
 #[test]
 fn test_assign_from_nonce_account_fail() {
 fn test_assign_from_nonce_account_fail() {
-    let bank = create_simple_test_arc_bank(100_000_000).0;
+    let (bank, _bank_forks) = create_simple_test_arc_bank(100_000_000);
     let nonce = Keypair::new();
     let nonce = Keypair::new();
     let nonce_account = AccountSharedData::new_data(
     let nonce_account = AccountSharedData::new_data(
         42_424_242,
         42_424_242,
@@ -5093,7 +5093,7 @@ fn test_assign_from_nonce_account_fail() {
 fn test_nonce_must_be_advanceable() {
 fn test_nonce_must_be_advanceable() {
     let mut bank = create_simple_test_bank(100_000_000);
     let mut bank = create_simple_test_bank(100_000_000);
     bank.feature_set = Arc::new(FeatureSet::all_enabled());
     bank.feature_set = Arc::new(FeatureSet::all_enabled());
-    let bank = bank.wrap_with_bank_forks_for_tests().0;
+    let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests();
     let nonce_keypair = Keypair::new();
     let nonce_keypair = Keypair::new();
     let nonce_authority = nonce_keypair.pubkey();
     let nonce_authority = nonce_keypair.pubkey();
     let durable_nonce = DurableNonce::from_blockhash(&bank.last_blockhash());
     let durable_nonce = DurableNonce::from_blockhash(&bank.last_blockhash());
@@ -5769,7 +5769,7 @@ fn test_check_ro_durable_nonce_fails() {
 
 
 #[test]
 #[test]
 fn test_collect_balances() {
 fn test_collect_balances() {
-    let parent = create_simple_test_arc_bank(500).0;
+    let (parent, _bank_forks) = create_simple_test_arc_bank(500);
     let bank0 = Arc::new(new_from_parent(parent));
     let bank0 = Arc::new(new_from_parent(parent));
 
 
     let keypair = Keypair::new();
     let keypair = Keypair::new();
@@ -5904,9 +5904,8 @@ fn test_transaction_with_duplicate_accounts_in_instruction() {
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee_no_rent(500);
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee_no_rent(500);
 
 
     let mock_program_id = Pubkey::from([2u8; 32]);
     let mock_program_id = Pubkey::from([2u8; 32]);
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, mock_program_id, MockBuiltin::vm)
-            .0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, mock_program_id, MockBuiltin::vm);
 
 
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
         let transaction_context = &invoke_context.transaction_context;
         let transaction_context = &invoke_context.transaction_context;
@@ -5961,9 +5960,8 @@ fn test_transaction_with_program_ids_passed_to_programs() {
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee_no_rent(500);
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee_no_rent(500);
 
 
     let mock_program_id = Pubkey::from([2u8; 32]);
     let mock_program_id = Pubkey::from([2u8; 32]);
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, mock_program_id, MockBuiltin::vm)
-            .0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, mock_program_id, MockBuiltin::vm);
 
 
     let from_pubkey = solana_sdk::pubkey::new_rand();
     let from_pubkey = solana_sdk::pubkey::new_rand();
     let to_pubkey = solana_sdk::pubkey::new_rand();
     let to_pubkey = solana_sdk::pubkey::new_rand();
@@ -6064,12 +6062,11 @@ fn test_incinerator() {
 fn test_duplicate_account_key() {
 fn test_duplicate_account_key() {
     solana_logger::setup();
     solana_logger::setup();
     let (genesis_config, mint_keypair) = create_genesis_config(500);
     let (genesis_config, mint_keypair) = create_genesis_config(500);
-    let bank = Bank::new_with_mockup_builtin_for_tests(
+    let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
         &genesis_config,
         &genesis_config,
         solana_vote_program::id(),
         solana_vote_program::id(),
         MockBuiltin::vm,
         MockBuiltin::vm,
-    )
-    .0;
+    );
 
 
     let from_pubkey = solana_sdk::pubkey::new_rand();
     let from_pubkey = solana_sdk::pubkey::new_rand();
     let to_pubkey = solana_sdk::pubkey::new_rand();
     let to_pubkey = solana_sdk::pubkey::new_rand();
@@ -6096,12 +6093,11 @@ fn test_duplicate_account_key() {
 fn test_process_transaction_with_too_many_account_locks() {
 fn test_process_transaction_with_too_many_account_locks() {
     solana_logger::setup();
     solana_logger::setup();
     let (genesis_config, mint_keypair) = create_genesis_config(500);
     let (genesis_config, mint_keypair) = create_genesis_config(500);
-    let bank = Bank::new_with_mockup_builtin_for_tests(
+    let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
         &genesis_config,
         &genesis_config,
         solana_vote_program::id(),
         solana_vote_program::id(),
         MockBuiltin::vm,
         MockBuiltin::vm,
-    )
-    .0;
+    );
 
 
     let from_pubkey = solana_sdk::pubkey::new_rand();
     let from_pubkey = solana_sdk::pubkey::new_rand();
     let to_pubkey = solana_sdk::pubkey::new_rand();
     let to_pubkey = solana_sdk::pubkey::new_rand();
@@ -6232,7 +6228,7 @@ fn test_fuzz_instructions() {
             (key, name.as_bytes().to_vec())
             (key, name.as_bytes().to_vec())
         })
         })
         .collect();
         .collect();
-    let bank = bank.wrap_with_bank_forks_for_tests().0;
+    let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests();
     let max_keys = 100;
     let max_keys = 100;
     let keys: Vec<_> = (0..max_keys)
     let keys: Vec<_> = (0..max_keys)
         .enumerate()
         .enumerate()
@@ -6435,9 +6431,8 @@ fn test_same_program_id_uses_unique_executable_accounts() {
 
 
     let (genesis_config, mint_keypair) = create_genesis_config(50000);
     let (genesis_config, mint_keypair) = create_genesis_config(50000);
     let program1_pubkey = solana_sdk::pubkey::new_rand();
     let program1_pubkey = solana_sdk::pubkey::new_rand();
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program1_pubkey, MockBuiltin::vm)
-            .0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program1_pubkey, MockBuiltin::vm);
 
 
     // Add a new program owned by the first
     // Add a new program owned by the first
     let program2_pubkey = solana_sdk::pubkey::new_rand();
     let program2_pubkey = solana_sdk::pubkey::new_rand();
@@ -6645,11 +6640,8 @@ fn test_add_builtin_no_overwrite() {
     let slot = 123;
     let slot = 123;
     let program_id = solana_sdk::pubkey::new_rand();
     let program_id = solana_sdk::pubkey::new_rand();
 
 
-    let mut bank = Arc::new(Bank::new_from_parent(
-        create_simple_test_arc_bank(100_000).0,
-        &Pubkey::default(),
-        slot,
-    ));
+    let (parent_bank, _bank_forks) = create_simple_test_arc_bank(100_000);
+    let mut bank = Arc::new(Bank::new_from_parent(parent_bank, &Pubkey::default(), slot));
     assert_eq!(bank.get_account_modified_slot(&program_id), None);
     assert_eq!(bank.get_account_modified_slot(&program_id), None);
 
 
     Arc::get_mut(&mut bank)
     Arc::get_mut(&mut bank)
@@ -6669,11 +6661,8 @@ fn test_add_builtin_loader_no_overwrite() {
     let slot = 123;
     let slot = 123;
     let loader_id = solana_sdk::pubkey::new_rand();
     let loader_id = solana_sdk::pubkey::new_rand();
 
 
-    let mut bank = Arc::new(Bank::new_from_parent(
-        create_simple_test_arc_bank(100_000).0,
-        &Pubkey::default(),
-        slot,
-    ));
+    let (parent_bank, _bank_forks) = create_simple_test_arc_bank(100_000);
+    let mut bank = Arc::new(Bank::new_from_parent(parent_bank, &Pubkey::default(), slot));
     assert_eq!(bank.get_account_modified_slot(&loader_id), None);
     assert_eq!(bank.get_account_modified_slot(&loader_id), None);
 
 
     Arc::get_mut(&mut bank)
     Arc::get_mut(&mut bank)
@@ -6839,11 +6828,8 @@ fn test_add_builtin_account_after_frozen() {
     let slot = 123;
     let slot = 123;
     let program_id = Pubkey::from_str("CiXgo2KHKSDmDnV1F6B69eWFgNAPiSBjjYvfB4cvRNre").unwrap();
     let program_id = Pubkey::from_str("CiXgo2KHKSDmDnV1F6B69eWFgNAPiSBjjYvfB4cvRNre").unwrap();
 
 
-    let bank = Bank::new_from_parent(
-        create_simple_test_arc_bank(100_000).0,
-        &Pubkey::default(),
-        slot,
-    );
+    let (parent_bank, _bank_forks) = create_simple_test_arc_bank(100_000);
+    let bank = Bank::new_from_parent(parent_bank, &Pubkey::default(), slot);
     bank.freeze();
     bank.freeze();
 
 
     bank.add_builtin_account("mock_program", &program_id);
     bank.add_builtin_account("mock_program", &program_id);
@@ -6970,11 +6956,8 @@ fn test_add_precompiled_account_after_frozen() {
     let slot = 123;
     let slot = 123;
     let program_id = Pubkey::from_str("CiXgo2KHKSDmDnV1F6B69eWFgNAPiSBjjYvfB4cvRNre").unwrap();
     let program_id = Pubkey::from_str("CiXgo2KHKSDmDnV1F6B69eWFgNAPiSBjjYvfB4cvRNre").unwrap();
 
 
-    let bank = Bank::new_from_parent(
-        create_simple_test_arc_bank(100_000).0,
-        &Pubkey::default(),
-        slot,
-    );
+    let (parent_bank, _bank_forks) = create_simple_test_arc_bank(100_000);
+    let bank = Bank::new_from_parent(parent_bank, &Pubkey::default(), slot);
     bank.freeze();
     bank.freeze();
 
 
     bank.add_precompiled_account(&program_id);
     bank.add_precompiled_account(&program_id);
@@ -7855,7 +7838,7 @@ fn test_bpf_loader_upgradeable_deploy_with_max_len() {
 
 
 #[test]
 #[test]
 fn test_compute_active_feature_set() {
 fn test_compute_active_feature_set() {
-    let bank0 = create_simple_test_arc_bank(100_000).0;
+    let (bank0, _bank_forks) = create_simple_test_arc_bank(100_000);
     let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
     let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
 
 
     let test_feature = "TestFeature11111111111111111111111111111111"
     let test_feature = "TestFeature11111111111111111111111111111111"
@@ -7906,7 +7889,7 @@ fn test_compute_active_feature_set() {
 
 
 #[test]
 #[test]
 fn test_reserved_account_keys() {
 fn test_reserved_account_keys() {
-    let bank0 = create_simple_test_arc_bank(100_000).0;
+    let (bank0, _bank_forks) = create_simple_test_arc_bank(100_000);
     let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
     let mut bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
     bank.feature_set = Arc::new(FeatureSet::default());
     bank.feature_set = Arc::new(FeatureSet::default());
 
 
@@ -8188,7 +8171,7 @@ fn test_timestamp_fast() {
 #[test]
 #[test]
 fn test_program_is_native_loader() {
 fn test_program_is_native_loader() {
     let (genesis_config, mint_keypair) = create_genesis_config(50000);
     let (genesis_config, mint_keypair) = create_genesis_config(50000);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     let tx = Transaction::new_signed_with_payer(
     let tx = Transaction::new_signed_with_payer(
         &[Instruction::new_with_bincode(
         &[Instruction::new_with_bincode(
@@ -9213,7 +9196,7 @@ fn test_tx_log_order() {
         &Pubkey::new_unique(),
         &Pubkey::new_unique(),
         bootstrap_validator_stake_lamports(),
         bootstrap_validator_stake_lamports(),
     );
     );
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     *bank.transaction_log_collector_config.write().unwrap() = TransactionLogCollectorConfig {
     *bank.transaction_log_collector_config.write().unwrap() = TransactionLogCollectorConfig {
         mentioned_addresses: HashSet::new(),
         mentioned_addresses: HashSet::new(),
         filter: TransactionLogCollectorFilter::All,
         filter: TransactionLogCollectorFilter::All,
@@ -9303,9 +9286,8 @@ fn test_tx_return_data() {
         bootstrap_validator_stake_lamports(),
         bootstrap_validator_stake_lamports(),
     );
     );
     let mock_program_id = Pubkey::from([2u8; 32]);
     let mock_program_id = Pubkey::from([2u8; 32]);
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, mock_program_id, MockBuiltin::vm)
-            .0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, mock_program_id, MockBuiltin::vm);
 
 
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
         let mock_program_id = Pubkey::from([2u8; 32]);
         let mock_program_id = Pubkey::from([2u8; 32]);
@@ -9505,8 +9487,8 @@ fn test_transfer_sysvar() {
     );
     );
     let program_id = solana_sdk::pubkey::new_rand();
     let program_id = solana_sdk::pubkey::new_rand();
 
 
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm).0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm);
 
 
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
         let transaction_context = &invoke_context.transaction_context;
         let transaction_context = &invoke_context.transaction_context;
@@ -9715,8 +9697,8 @@ fn test_compute_budget_program_noop() {
         bootstrap_validator_stake_lamports(),
         bootstrap_validator_stake_lamports(),
     );
     );
     let program_id = solana_sdk::pubkey::new_rand();
     let program_id = solana_sdk::pubkey::new_rand();
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm).0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm);
 
 
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
         let compute_budget = invoke_context.get_compute_budget();
         let compute_budget = invoke_context.get_compute_budget();
@@ -9760,8 +9742,8 @@ fn test_compute_request_instruction() {
         bootstrap_validator_stake_lamports(),
         bootstrap_validator_stake_lamports(),
     );
     );
     let program_id = solana_sdk::pubkey::new_rand();
     let program_id = solana_sdk::pubkey::new_rand();
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm).0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm);
 
 
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
     declare_process_instruction!(MockBuiltin, 1, |invoke_context| {
         let compute_budget = invoke_context.get_compute_budget();
         let compute_budget = invoke_context.get_compute_budget();
@@ -9806,8 +9788,8 @@ fn test_failed_compute_request_instruction() {
     );
     );
 
 
     let program_id = solana_sdk::pubkey::new_rand();
     let program_id = solana_sdk::pubkey::new_rand();
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm).0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm);
 
 
     let payer0_keypair = Keypair::new();
     let payer0_keypair = Keypair::new();
     let payer1_keypair = Keypair::new();
     let payer1_keypair = Keypair::new();
@@ -9979,7 +9961,7 @@ fn test_call_precomiled_program() {
         ..
         ..
     } = create_genesis_config_with_leader(42, &Pubkey::new_unique(), 42);
     } = create_genesis_config_with_leader(42, &Pubkey::new_unique(), 42);
     activate_all_features(&mut genesis_config);
     activate_all_features(&mut genesis_config);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     // libsecp256k1
     // libsecp256k1
     // Since libsecp256k1 is still using the old version of rand, this test
     // Since libsecp256k1 is still using the old version of rand, this test
@@ -10244,7 +10226,7 @@ fn test_an_empty_instruction_without_program() {
     let message = Message::new(&[ix], Some(&mint_keypair.pubkey()));
     let message = Message::new(&[ix], Some(&mint_keypair.pubkey()));
     let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
     let tx = Transaction::new(&[&mint_keypair], message, genesis_config.hash());
 
 
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     assert_eq!(
     assert_eq!(
         bank.process_transaction(&tx).unwrap_err(),
         bank.process_transaction(&tx).unwrap_err(),
         TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId),
         TransactionError::InstructionError(0, InstructionError::UnsupportedProgramId),
@@ -10272,7 +10254,7 @@ fn test_accounts_data_size_with_good_transaction() {
     const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH;
     const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH;
     let (genesis_config, mint_keypair) = create_genesis_config(1_000 * LAMPORTS_PER_SOL);
     let (genesis_config, mint_keypair) = create_genesis_config(1_000 * LAMPORTS_PER_SOL);
     let bank = Bank::new_for_tests(&genesis_config);
     let bank = Bank::new_for_tests(&genesis_config);
-    let bank = bank.wrap_with_bank_forks_for_tests().0;
+    let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests();
     let transaction = system_transaction::create_account(
     let transaction = system_transaction::create_account(
         &mint_keypair,
         &mint_keypair,
         &Keypair::new(),
         &Keypair::new(),
@@ -10313,7 +10295,7 @@ fn test_accounts_data_size_with_bad_transaction() {
     const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH;
     const ACCOUNT_SIZE: u64 = MAX_PERMITTED_DATA_LENGTH;
     let (genesis_config, _mint_keypair) = create_genesis_config(1_000 * LAMPORTS_PER_SOL);
     let (genesis_config, _mint_keypair) = create_genesis_config(1_000 * LAMPORTS_PER_SOL);
     let bank = Bank::new_for_tests(&genesis_config);
     let bank = Bank::new_for_tests(&genesis_config);
-    let bank = bank.wrap_with_bank_forks_for_tests().0;
+    let (bank, _bank_forks) = bank.wrap_with_bank_forks_for_tests();
     let transaction = system_transaction::create_account(
     let transaction = system_transaction::create_account(
         &Keypair::new(),
         &Keypair::new(),
         &Keypair::new(),
         &Keypair::new(),
@@ -10430,12 +10412,11 @@ fn test_invalid_rent_state_changes_existing_accounts() {
         ),
         ),
     );
     );
 
 
-    let bank = Bank::new_with_mockup_builtin_for_tests(
+    let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
         &genesis_config,
         &genesis_config,
         mock_program_id,
         mock_program_id,
         MockTransferBuiltin::vm,
         MockTransferBuiltin::vm,
-    )
-    .0;
+    );
     let recent_blockhash = bank.last_blockhash();
     let recent_blockhash = bank.last_blockhash();
 
 
     let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
     let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
@@ -10517,12 +10498,11 @@ fn test_invalid_rent_state_changes_new_accounts() {
     let account_data_size = 100;
     let account_data_size = 100;
     let rent_exempt_minimum = genesis_config.rent.minimum_balance(account_data_size);
     let rent_exempt_minimum = genesis_config.rent.minimum_balance(account_data_size);
 
 
-    let bank = Bank::new_with_mockup_builtin_for_tests(
+    let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
         &genesis_config,
         &genesis_config,
         mock_program_id,
         mock_program_id,
         MockTransferBuiltin::vm,
         MockTransferBuiltin::vm,
-    )
-    .0;
+    );
     let recent_blockhash = bank.last_blockhash();
     let recent_blockhash = bank.last_blockhash();
 
 
     let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
     let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
@@ -10580,12 +10560,11 @@ fn test_drained_created_account() {
     // Create legacy accounts of various kinds
     // Create legacy accounts of various kinds
     let created_keypair = Keypair::new();
     let created_keypair = Keypair::new();
 
 
-    let bank = Bank::new_with_mockup_builtin_for_tests(
+    let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
         &genesis_config,
         &genesis_config,
         mock_program_id,
         mock_program_id,
         MockTransferBuiltin::vm,
         MockTransferBuiltin::vm,
-    )
-    .0;
+    );
     let recent_blockhash = bank.last_blockhash();
     let recent_blockhash = bank.last_blockhash();
 
 
     // Create and drain a small data size account
     // Create and drain a small data size account
@@ -10696,7 +10675,7 @@ fn test_rent_state_changes_sysvars() {
         Account::from(validator_vote_account),
         Account::from(validator_vote_account),
     );
     );
 
 
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     // Ensure transactions with sysvars succeed, even though sysvars appear RentPaying by balance
     // Ensure transactions with sysvars succeed, even though sysvars appear RentPaying by balance
     let tx = Transaction::new_signed_with_payer(
     let tx = Transaction::new_signed_with_payer(
@@ -10739,7 +10718,7 @@ fn test_invalid_rent_state_changes_fee_payer() {
         Account::new(rent_exempt_minimum, 0, &system_program::id()),
         Account::new(rent_exempt_minimum, 0, &system_program::id()),
     );
     );
 
 
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let recent_blockhash = bank.last_blockhash();
     let recent_blockhash = bank.last_blockhash();
 
 
     let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
     let check_account_is_rent_exempt = |pubkey: &Pubkey| -> bool {
@@ -10968,7 +10947,7 @@ fn test_rent_state_incinerator() {
     genesis_config.rent = Rent::default();
     genesis_config.rent = Rent::default();
     let rent_exempt_minimum = genesis_config.rent.minimum_balance(0);
     let rent_exempt_minimum = genesis_config.rent.minimum_balance(0);
 
 
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     for amount in [rent_exempt_minimum - 1, rent_exempt_minimum] {
     for amount in [rent_exempt_minimum - 1, rent_exempt_minimum] {
         bank.transfer(amount, &mint_keypair, &solana_sdk::incinerator::id())
         bank.transfer(amount, &mint_keypair, &solana_sdk::incinerator::id())
@@ -11138,12 +11117,11 @@ fn test_resize_and_rent() {
     activate_all_features(&mut genesis_config);
     activate_all_features(&mut genesis_config);
 
 
     let mock_program_id = Pubkey::new_unique();
     let mock_program_id = Pubkey::new_unique();
-    let bank = Bank::new_with_mockup_builtin_for_tests(
+    let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
         &genesis_config,
         &genesis_config,
         mock_program_id,
         mock_program_id,
         MockReallocBuiltin::vm,
         MockReallocBuiltin::vm,
-    )
-    .0;
+    );
 
 
     let recent_blockhash = bank.last_blockhash();
     let recent_blockhash = bank.last_blockhash();
 
 
@@ -11414,12 +11392,11 @@ fn test_accounts_data_size_and_resize_transactions() {
         ..
         ..
     } = genesis_utils::create_genesis_config(100 * LAMPORTS_PER_SOL);
     } = genesis_utils::create_genesis_config(100 * LAMPORTS_PER_SOL);
     let mock_program_id = Pubkey::new_unique();
     let mock_program_id = Pubkey::new_unique();
-    let bank = Bank::new_with_mockup_builtin_for_tests(
+    let (bank, _bank_forks) = Bank::new_with_mockup_builtin_for_tests(
         &genesis_config,
         &genesis_config,
         mock_program_id,
         mock_program_id,
         MockReallocBuiltin::vm,
         MockReallocBuiltin::vm,
-    )
-    .0;
+    );
 
 
     let recent_blockhash = bank.last_blockhash();
     let recent_blockhash = bank.last_blockhash();
 
 
@@ -11669,7 +11646,7 @@ fn test_cap_accounts_data_allocations_per_transaction() {
             / MAX_PERMITTED_DATA_LENGTH as usize;
             / MAX_PERMITTED_DATA_LENGTH as usize;
 
 
     let (genesis_config, mint_keypair) = create_genesis_config(1_000_000 * LAMPORTS_PER_SOL);
     let (genesis_config, mint_keypair) = create_genesis_config(1_000_000 * LAMPORTS_PER_SOL);
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
 
 
     let mut instructions = Vec::new();
     let mut instructions = Vec::new();
     let mut keypairs = vec![mint_keypair.insecure_clone()];
     let mut keypairs = vec![mint_keypair.insecure_clone()];
@@ -11876,7 +11853,7 @@ fn test_calculate_fee_with_request_heap_frame_flag() {
 fn test_is_in_slot_hashes_history() {
 fn test_is_in_slot_hashes_history() {
     use solana_sdk::slot_hashes::MAX_ENTRIES;
     use solana_sdk::slot_hashes::MAX_ENTRIES;
 
 
-    let bank0 = create_simple_test_arc_bank(1).0;
+    let (bank0, _bank_forks) = create_simple_test_arc_bank(1);
     assert!(!bank0.is_in_slot_hashes_history(&0));
     assert!(!bank0.is_in_slot_hashes_history(&0));
     assert!(!bank0.is_in_slot_hashes_history(&1));
     assert!(!bank0.is_in_slot_hashes_history(&1));
     let mut last_bank = bank0;
     let mut last_bank = bank0;
@@ -12183,7 +12160,7 @@ fn test_squash_timing_add_assign() {
 #[test]
 #[test]
 fn test_system_instruction_allocate() {
 fn test_system_instruction_allocate() {
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.0));
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.0));
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let bank_client = BankClient::new_shared(bank);
     let bank_client = BankClient::new_shared(bank);
     let data_len = 2;
     let data_len = 2;
     let amount = genesis_config.rent.minimum_balance(data_len);
     let amount = genesis_config.rent.minimum_balance(data_len);
@@ -12310,7 +12287,7 @@ fn test_create_zero_lamport_without_clean() {
 #[test]
 #[test]
 fn test_system_instruction_assign_with_seed() {
 fn test_system_instruction_assign_with_seed() {
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.0));
     let (genesis_config, mint_keypair) = create_genesis_config_no_tx_fee(sol_to_lamports(1.0));
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let bank_client = BankClient::new_shared(bank);
     let bank_client = BankClient::new_shared(bank);
 
 
     let alice_keypair = Keypair::new();
     let alice_keypair = Keypair::new();
@@ -12351,7 +12328,7 @@ fn test_system_instruction_unsigned_transaction() {
     let amount = genesis_config.rent.minimum_balance(0);
     let amount = genesis_config.rent.minimum_balance(0);
 
 
     // Fund to account to bypass AccountNotFound error
     // Fund to account to bypass AccountNotFound error
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let bank_client = BankClient::new_shared(bank);
     let bank_client = BankClient::new_shared(bank);
     bank_client
     bank_client
         .transfer_and_confirm(amount, &alice_keypair, &mallory_pubkey)
         .transfer_and_confirm(amount, &alice_keypair, &mallory_pubkey)
@@ -12855,8 +12832,8 @@ fn test_get_accounts_for_bank_hash_details(skip_rewrites: bool) {
 fn test_failed_simulation_compute_units() {
 fn test_failed_simulation_compute_units() {
     let (genesis_config, mint_keypair) = create_genesis_config(LAMPORTS_PER_SOL);
     let (genesis_config, mint_keypair) = create_genesis_config(LAMPORTS_PER_SOL);
     let program_id = Pubkey::new_unique();
     let program_id = Pubkey::new_unique();
-    let bank =
-        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm).0;
+    let (bank, _bank_forks) =
+        Bank::new_with_mockup_builtin_for_tests(&genesis_config, program_id, MockBuiltin::vm);
 
 
     const TEST_UNITS: u64 = 10_000;
     const TEST_UNITS: u64 = 10_000;
     const MOCK_BUILTIN_UNITS: u64 = 1;
     const MOCK_BUILTIN_UNITS: u64 = 1;

+ 1 - 1
runtime/src/bank_client.rs

@@ -321,7 +321,7 @@ mod tests {
         let jane_doe_keypair = Keypair::new();
         let jane_doe_keypair = Keypair::new();
         let jane_pubkey = jane_doe_keypair.pubkey();
         let jane_pubkey = jane_doe_keypair.pubkey();
         let doe_keypairs = vec![&john_doe_keypair, &jane_doe_keypair];
         let doe_keypairs = vec![&john_doe_keypair, &jane_doe_keypair];
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let bank_client = BankClient::new_shared(bank);
         let bank_client = BankClient::new_shared(bank);
         let amount = genesis_config.rent.minimum_balance(0);
         let amount = genesis_config.rent.minimum_balance(0);
 
 

+ 9 - 1
runtime/src/bank_forks.rs

@@ -134,7 +134,7 @@ impl BankForks {
             scheduler_pool: None,
             scheduler_pool: None,
         }));
         }));
 
 
-        root_bank.set_fork_graph_in_program_cache(bank_forks.clone());
+        root_bank.set_fork_graph_in_program_cache(Arc::downgrade(&bank_forks));
         bank_forks
         bank_forks
     }
     }
 
 
@@ -751,6 +751,14 @@ mod tests {
         std::{sync::atomic::Ordering::Relaxed, time::Duration},
         std::{sync::atomic::Ordering::Relaxed, time::Duration},
     };
     };
 
 
+    #[test]
+    fn test_bank_forks_new_rw_arc_memory_leak() {
+        for _ in 0..1000 {
+            let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
+            BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
+        }
+    }
+
     #[test]
     #[test]
     fn test_bank_forks_new() {
     fn test_bank_forks_new() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);

+ 3 - 3
runtime/tests/stake.rs

@@ -142,7 +142,7 @@ fn test_stake_create_and_split_single_signature() {
 
 
     let staker_pubkey = staker_keypair.pubkey();
     let staker_pubkey = staker_keypair.pubkey();
 
 
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let bank_client = BankClient::new_shared(bank.clone());
     let bank_client = BankClient::new_shared(bank.clone());
 
 
     let stake_address =
     let stake_address =
@@ -218,7 +218,7 @@ fn test_stake_create_and_split_to_existing_system_account() {
 
 
     let staker_pubkey = staker_keypair.pubkey();
     let staker_pubkey = staker_keypair.pubkey();
 
 
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let bank_client = BankClient::new_shared(bank.clone());
     let bank_client = BankClient::new_shared(bank.clone());
 
 
     let stake_address =
     let stake_address =
@@ -593,7 +593,7 @@ fn test_create_stake_account_from_seed() {
         &solana_sdk::pubkey::new_rand(),
         &solana_sdk::pubkey::new_rand(),
         1_000_000,
         1_000_000,
     );
     );
-    let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+    let (bank, _bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
     let mint_pubkey = mint_keypair.pubkey();
     let mint_pubkey = mint_keypair.pubkey();
     let bank_client = BankClient::new_shared(bank.clone());
     let bank_client = BankClient::new_shared(bank.clone());
 
 

+ 10 - 10
stake-accounts/src/stake_accounts.rs

@@ -283,7 +283,7 @@ pub(crate) fn move_stake_accounts(
 mod tests {
 mod tests {
     use {
     use {
         super::*,
         super::*,
-        solana_runtime::{bank::Bank, bank_client::BankClient},
+        solana_runtime::{bank::Bank, bank_client::BankClient, bank_forks::BankForks},
         solana_sdk::{
         solana_sdk::{
             account::{AccountSharedData, ReadableAccount},
             account::{AccountSharedData, ReadableAccount},
             client::SyncClient,
             client::SyncClient,
@@ -292,16 +292,16 @@ mod tests {
             stake::state::StakeStateV2,
             stake::state::StakeStateV2,
         },
         },
         solana_stake_program::stake_state,
         solana_stake_program::stake_state,
-        std::sync::Arc,
+        std::sync::{Arc, RwLock},
     };
     };
 
 
-    fn create_bank(lamports: u64) -> (Arc<Bank>, Keypair, u64, u64) {
+    fn create_bank(lamports: u64) -> (Arc<Bank>, Arc<RwLock<BankForks>>, Keypair, u64, u64) {
         let (mut genesis_config, mint_keypair) = create_genesis_config(lamports);
         let (mut genesis_config, mint_keypair) = create_genesis_config(lamports);
         genesis_config.fee_rate_governor = solana_sdk::fee_calculator::FeeRateGovernor::new(0, 0);
         genesis_config.fee_rate_governor = solana_sdk::fee_calculator::FeeRateGovernor::new(0, 0);
-        let bank = Bank::new_with_bank_forks_for_tests(&genesis_config).0;
+        let (bank, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
         let stake_rent = bank.get_minimum_balance_for_rent_exemption(StakeStateV2::size_of());
         let stake_rent = bank.get_minimum_balance_for_rent_exemption(StakeStateV2::size_of());
         let system_rent = bank.get_minimum_balance_for_rent_exemption(0);
         let system_rent = bank.get_minimum_balance_for_rent_exemption(0);
-        (bank, mint_keypair, stake_rent, system_rent)
+        (bank, bank_forks, mint_keypair, stake_rent, system_rent)
     }
     }
 
 
     fn create_account<C: SyncClient>(
     fn create_account<C: SyncClient>(
@@ -355,7 +355,7 @@ mod tests {
 
 
     #[test]
     #[test]
     fn test_new_derived_stake_account() {
     fn test_new_derived_stake_account() {
-        let (bank, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
+        let (bank, _bank_forks, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
         let funding_pubkey = funding_keypair.pubkey();
         let funding_pubkey = funding_keypair.pubkey();
         let bank_client = BankClient::new_shared(bank);
         let bank_client = BankClient::new_shared(bank);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
@@ -392,7 +392,7 @@ mod tests {
 
 
     #[test]
     #[test]
     fn test_authorize_stake_accounts() {
     fn test_authorize_stake_accounts() {
-        let (bank, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
+        let (bank, _bank_forks, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
         let funding_pubkey = funding_keypair.pubkey();
         let funding_pubkey = funding_keypair.pubkey();
         let bank_client = BankClient::new_shared(bank);
         let bank_client = BankClient::new_shared(bank);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
@@ -454,7 +454,7 @@ mod tests {
 
 
     #[test]
     #[test]
     fn test_lockup_stake_accounts() {
     fn test_lockup_stake_accounts() {
-        let (bank, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
+        let (bank, _bank_forks, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
         let funding_pubkey = funding_keypair.pubkey();
         let funding_pubkey = funding_keypair.pubkey();
         let bank_client = BankClient::new_shared(bank);
         let bank_client = BankClient::new_shared(bank);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
@@ -545,7 +545,7 @@ mod tests {
 
 
     #[test]
     #[test]
     fn test_rebase_stake_accounts() {
     fn test_rebase_stake_accounts() {
-        let (bank, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
+        let (bank, _bank_forks, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
         let funding_pubkey = funding_keypair.pubkey();
         let funding_pubkey = funding_keypair.pubkey();
         let bank_client = BankClient::new_shared(bank);
         let bank_client = BankClient::new_shared(bank);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
@@ -608,7 +608,7 @@ mod tests {
 
 
     #[test]
     #[test]
     fn test_move_stake_accounts() {
     fn test_move_stake_accounts() {
-        let (bank, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
+        let (bank, _bank_forks, funding_keypair, stake_rent, system_rent) = create_bank(10_000_000);
         let funding_pubkey = funding_keypair.pubkey();
         let funding_pubkey = funding_keypair.pubkey();
         let bank_client = BankClient::new_shared(bank);
         let bank_client = BankClient::new_shared(bank);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);
         let fee_payer_keypair = create_account(&bank_client, &funding_keypair, system_rent);

+ 8 - 4
svm/src/transaction_processor.rs

@@ -1305,8 +1305,9 @@ mod tests {
     fn test_replenish_program_cache_with_nonexistent_accounts() {
     fn test_replenish_program_cache_with_nonexistent_accounts() {
         let mock_bank = MockBankCallback::default();
         let mock_bank = MockBankCallback::default();
         let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
         let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
+        let fork_graph = Arc::new(RwLock::new(TestForkGraph {}));
         batch_processor.program_cache.write().unwrap().fork_graph =
         batch_processor.program_cache.write().unwrap().fork_graph =
-            Some(Arc::new(RwLock::new(TestForkGraph {})));
+            Some(Arc::downgrade(&fork_graph));
         let key = Pubkey::new_unique();
         let key = Pubkey::new_unique();
 
 
         let mut account_maps: HashMap<Pubkey, u64> = HashMap::new();
         let mut account_maps: HashMap<Pubkey, u64> = HashMap::new();
@@ -1319,8 +1320,9 @@ mod tests {
     fn test_replenish_program_cache() {
     fn test_replenish_program_cache() {
         let mock_bank = MockBankCallback::default();
         let mock_bank = MockBankCallback::default();
         let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
         let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
+        let fork_graph = Arc::new(RwLock::new(TestForkGraph {}));
         batch_processor.program_cache.write().unwrap().fork_graph =
         batch_processor.program_cache.write().unwrap().fork_graph =
-            Some(Arc::new(RwLock::new(TestForkGraph {})));
+            Some(Arc::downgrade(&fork_graph));
         let key = Pubkey::new_unique();
         let key = Pubkey::new_unique();
 
 
         let mut account_data = AccountSharedData::default();
         let mut account_data = AccountSharedData::default();
@@ -1800,8 +1802,9 @@ mod tests {
     fn test_add_builtin() {
     fn test_add_builtin() {
         let mock_bank = MockBankCallback::default();
         let mock_bank = MockBankCallback::default();
         let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
         let batch_processor = TransactionBatchProcessor::<TestForkGraph>::default();
+        let fork_graph = Arc::new(RwLock::new(TestForkGraph {}));
         batch_processor.program_cache.write().unwrap().fork_graph =
         batch_processor.program_cache.write().unwrap().fork_graph =
-            Some(Arc::new(RwLock::new(TestForkGraph {})));
+            Some(Arc::downgrade(&fork_graph));
 
 
         let key = Pubkey::new_unique();
         let key = Pubkey::new_unique();
         let name = "a_builtin_name";
         let name = "a_builtin_name";
@@ -1843,8 +1846,9 @@ mod tests {
     fn fast_concur_test() {
     fn fast_concur_test() {
         let mut mock_bank = MockBankCallback::default();
         let mut mock_bank = MockBankCallback::default();
         let batch_processor = TransactionBatchProcessor::<TestForkGraph>::new(5, 5, HashSet::new());
         let batch_processor = TransactionBatchProcessor::<TestForkGraph>::new(5, 5, HashSet::new());
+        let fork_graph = Arc::new(RwLock::new(TestForkGraph {}));
         batch_processor.program_cache.write().unwrap().fork_graph =
         batch_processor.program_cache.write().unwrap().fork_graph =
-            Some(Arc::new(RwLock::new(TestForkGraph {})));
+            Some(Arc::downgrade(&fork_graph));
 
 
         let programs = vec![
         let programs = vec![
             deploy_program("hello-solana".to_string(), &mut mock_bank),
             deploy_program("hello-solana".to_string(), &mut mock_bank),

+ 2 - 1
svm/tests/conformance.rs

@@ -245,6 +245,7 @@ fn run_fixture(fixture: InstrFixture, filename: OsString, execute_as_instr: bool
     mock_bank.override_feature_set(feature_set);
     mock_bank.override_feature_set(feature_set);
     let batch_processor = TransactionBatchProcessor::<MockForkGraph>::new(42, 2, HashSet::new());
     let batch_processor = TransactionBatchProcessor::<MockForkGraph>::new(42, 2, HashSet::new());
 
 
+    let fork_graph = Arc::new(RwLock::new(MockForkGraph {}));
     {
     {
         let mut program_cache = batch_processor.program_cache.write().unwrap();
         let mut program_cache = batch_processor.program_cache.write().unwrap();
         program_cache.environments = ProgramRuntimeEnvironments {
         program_cache.environments = ProgramRuntimeEnvironments {
@@ -254,7 +255,7 @@ fn run_fixture(fixture: InstrFixture, filename: OsString, execute_as_instr: bool
                 FunctionRegistry::default(),
                 FunctionRegistry::default(),
             )),
             )),
         };
         };
-        program_cache.fork_graph = Some(Arc::new(RwLock::new(MockForkGraph {})));
+        program_cache.fork_graph = Some(Arc::downgrade(&fork_graph.clone()));
     }
     }
 
 
     batch_processor.fill_missing_sysvar_cache_entries(&mock_bank);
     batch_processor.fill_missing_sysvar_cache_entries(&mock_bank);

+ 5 - 1
svm/tests/integration_test.rs

@@ -129,6 +129,7 @@ fn create_custom_environment<'a>() -> BuiltinProgram<InvokeContext<'a>> {
 }
 }
 
 
 fn create_executable_environment(
 fn create_executable_environment(
+    fork_graph: Arc<RwLock<MockForkGraph>>,
     mock_bank: &mut MockBankCallback,
     mock_bank: &mut MockBankCallback,
     program_cache: &mut ProgramCache<MockForkGraph>,
     program_cache: &mut ProgramCache<MockForkGraph>,
 ) {
 ) {
@@ -141,7 +142,7 @@ fn create_executable_environment(
         )),
         )),
     };
     };
 
 
-    program_cache.fork_graph = Some(Arc::new(RwLock::new(MockForkGraph {})));
+    program_cache.fork_graph = Some(Arc::downgrade(&fork_graph));
 
 
     // We must fill in the sysvar cache entries
     // We must fill in the sysvar cache entries
     let time_now = SystemTime::now()
     let time_now = SystemTime::now()
@@ -446,7 +447,10 @@ fn svm_integration() {
         HashSet::new(),
         HashSet::new(),
     );
     );
 
 
+    let fork_graph = Arc::new(RwLock::new(MockForkGraph {}));
+
     create_executable_environment(
     create_executable_environment(
+        fork_graph.clone(),
         &mut mock_bank,
         &mut mock_bank,
         &mut batch_processor.program_cache.write().unwrap(),
         &mut batch_processor.program_cache.write().unwrap(),
     );
     );

+ 20 - 17
unified-scheduler-pool/src/lib.rs

@@ -1477,7 +1477,10 @@ mod tests {
             system_transaction,
             system_transaction,
             transaction::{SanitizedTransaction, TransactionError},
             transaction::{SanitizedTransaction, TransactionError},
         },
         },
-        std::{sync::Arc, thread::JoinHandle},
+        std::{
+            sync::{Arc, RwLock},
+            thread::JoinHandle,
+        },
     };
     };
 
 
     #[derive(Debug)]
     #[derive(Debug)]
@@ -1756,7 +1759,7 @@ mod tests {
             ..
             ..
         } = create_genesis_config(10_000);
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
 
 
         let context = SchedulingContext::new(bank.clone());
         let context = SchedulingContext::new(bank.clone());
 
 
@@ -1824,7 +1827,7 @@ mod tests {
 
 
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
 
 
         let context = SchedulingContext::new(bank.clone());
         let context = SchedulingContext::new(bank.clone());
 
 
@@ -1876,7 +1879,7 @@ mod tests {
             ..
             ..
         } = create_genesis_config(10_000);
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
 
 
         let context = SchedulingContext::new(bank.clone());
         let context = SchedulingContext::new(bank.clone());
 
 
@@ -1957,7 +1960,7 @@ mod tests {
         ));
         ));
 
 
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let pool = SchedulerPool::<PooledScheduler<FaultyHandler>, _>::new(
         let pool = SchedulerPool::<PooledScheduler<FaultyHandler>, _>::new(
             None,
             None,
@@ -2050,7 +2053,7 @@ mod tests {
         } = create_genesis_config(10_000);
         } = create_genesis_config(10_000);
 
 
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let pool = SchedulerPool::<PooledScheduler<CountingHandler>, _>::new(
         let pool = SchedulerPool::<PooledScheduler<CountingHandler>, _>::new(
             None,
             None,
@@ -2197,12 +2200,12 @@ mod tests {
         assert!(!child_bank.has_installed_scheduler());
         assert!(!child_bank.has_installed_scheduler());
     }
     }
 
 
-    fn setup_dummy_fork_graph(bank: Bank) -> Arc<Bank> {
+    fn setup_dummy_fork_graph(bank: Bank) -> (Arc<Bank>, Arc<RwLock<BankForks>>) {
         let slot = bank.slot();
         let slot = bank.slot();
         let bank_fork = BankForks::new_rw_arc(bank);
         let bank_fork = BankForks::new_rw_arc(bank);
         let bank = bank_fork.read().unwrap().get(slot).unwrap();
         let bank = bank_fork.read().unwrap().get(slot).unwrap();
-        bank.set_fork_graph_in_program_cache(bank_fork);
-        bank
+        bank.set_fork_graph_in_program_cache(Arc::downgrade(&bank_fork));
+        (bank, bank_fork)
     }
     }
 
 
     #[test]
     #[test]
@@ -2221,7 +2224,7 @@ mod tests {
             genesis_config.hash(),
             genesis_config.hash(),
         ));
         ));
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let pool =
         let pool =
             DefaultSchedulerPool::new_dyn(None, None, None, None, ignored_prioritization_fee_cache);
             DefaultSchedulerPool::new_dyn(None, None, None, None, ignored_prioritization_fee_cache);
@@ -2255,7 +2258,7 @@ mod tests {
             ..
             ..
         } = create_genesis_config(10_000);
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
 
 
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let pool_raw = DefaultSchedulerPool::do_new(
         let pool_raw = DefaultSchedulerPool::do_new(
@@ -2384,7 +2387,7 @@ mod tests {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
 
 
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
 
 
         // Use 2 transactions with different timings to deliberately cover the two code paths of
         // Use 2 transactions with different timings to deliberately cover the two code paths of
         // notifying panics in the handler threads, taken conditionally depending on whether the
         // notifying panics in the handler threads, taken conditionally depending on whether the
@@ -2466,7 +2469,7 @@ mod tests {
         } = create_genesis_config(10_000);
         } = create_genesis_config(10_000);
 
 
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let pool = SchedulerPool::<PooledScheduler<CountingFaultyHandler>, _>::new(
         let pool = SchedulerPool::<PooledScheduler<CountingFaultyHandler>, _>::new(
             None,
             None,
@@ -2558,7 +2561,7 @@ mod tests {
         ));
         ));
 
 
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let pool = SchedulerPool::<PooledScheduler<StallingHandler>, _>::new_dyn(
         let pool = SchedulerPool::<PooledScheduler<StallingHandler>, _>::new_dyn(
             None,
             None,
@@ -2619,7 +2622,7 @@ mod tests {
 
 
         // Create two banks for two contexts
         // Create two banks for two contexts
         let bank0 = Bank::new_for_tests(&genesis_config);
         let bank0 = Bank::new_for_tests(&genesis_config);
-        let bank0 = setup_dummy_fork_graph(bank0);
+        let bank0 = setup_dummy_fork_graph(bank0).0;
         let bank1 = Arc::new(Bank::new_from_parent(
         let bank1 = Arc::new(Bank::new_from_parent(
             bank0.clone(),
             bank0.clone(),
             &Pubkey::default(),
             &Pubkey::default(),
@@ -2817,7 +2820,7 @@ mod tests {
                 slot.checked_add(1).unwrap(),
                 slot.checked_add(1).unwrap(),
             );
             );
         }
         }
-        let bank = setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = setup_dummy_fork_graph(bank);
         let context = SchedulingContext::new(bank.clone());
         let context = SchedulingContext::new(bank.clone());
 
 
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));
@@ -2888,7 +2891,7 @@ mod tests {
             ..
             ..
         } = create_genesis_config(10_000);
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank = &setup_dummy_fork_graph(bank);
+        let (bank, _bank_forks) = &setup_dummy_fork_graph(bank);
 
 
         let mut tx = system_transaction::transfer(
         let mut tx = system_transaction::transfer(
             mint_keypair,
             mint_keypair,