Преглед на файлове

v1.17: Initialize fork graph in program cache during bank_forks creation (backport of #33810) (#33817)

* Initialize fork graph in program cache during bank_forks creation (#33810)

* Initialize fork graph in program cache during bank_forks creation

* rename BankForks::new to BankForks::new_rw_arc

* fix compilation

* no need to set fork_graph on insert()

* fix partition tests

(cherry picked from commit 9d42cd7efe869223040f68c0a9b2bdfa99f1018a)

# Conflicts:
#	core/src/repair/repair_service.rs
#	core/tests/epoch_accounts_hash.rs
#	ledger/src/blockstore_processor.rs
#	rpc/src/rpc_service.rs
#	runtime/src/bank/tests.rs

* fix merge conflicts

---------

Co-authored-by: Pankaj Garg <pankaj@solana.com>
mergify[bot] преди 2 години
родител
ревизия
22f44d0518
променени са 50 файла, в които са добавени 479 реда и са изтрити 399 реда
  1. 167 143
      Cargo.lock
  2. 1 1
      banking-bench/src/main.rs
  3. 2 2
      banks-client/src/lib.rs
  4. 6 6
      client-test/tests/client.rs
  5. 2 2
      core/benches/banking_stage.rs
  6. 8 2
      core/benches/consensus.rs
  7. 5 5
      core/src/banking_stage.rs
  8. 1 1
      core/src/banking_stage/consume_worker.rs
  9. 1 1
      core/src/banking_stage/forward_worker.rs
  10. 1 1
      core/src/banking_stage/forwarder.rs
  11. 5 5
      core/src/cluster_info_vote_listener.rs
  12. 2 1
      core/src/commitment_service.rs
  13. 2 1
      core/src/consensus/heaviest_subtree_fork_choice.rs
  14. 1 1
      core/src/repair/ancestor_hashes_service.rs
  15. 1 1
      core/src/repair/quic_endpoint.rs
  16. 2 2
      core/src/repair/repair_service.rs
  17. 5 5
      core/src/repair/serve_repair.rs
  18. 23 15
      core/src/replay_stage.rs
  19. 2 3
      core/src/tvu.rs
  20. 3 3
      core/src/validator.rs
  21. 11 5
      core/src/vote_simulator.rs
  22. 17 8
      core/tests/epoch_accounts_hash.rs
  23. 53 29
      core/tests/snapshots.rs
  24. 7 11
      gossip/src/duplicate_shred_handler.rs
  25. 1 1
      gossip/tests/gossip.rs
  26. 1 13
      ledger/src/bank_forks_utils.rs
  27. 9 6
      ledger/src/blockstore_processor.rs
  28. 1 1
      program-runtime/src/loaded_programs.rs
  29. 1 1
      program-test/src/lib.rs
  30. 1 1
      rpc/src/optimistically_confirmed_bank_tracker.rs
  31. 3 6
      rpc/src/rpc.rs
  32. 1 1
      rpc/src/rpc_health.rs
  33. 12 14
      rpc/src/rpc_pubsub.rs
  34. 1 1
      rpc/src/rpc_pubsub_service.rs
  35. 2 2
      rpc/src/rpc_service.rs
  36. 2 2
      rpc/src/rpc_subscription_tracker.rs
  37. 20 18
      rpc/src/rpc_subscriptions.rs
  38. 2 2
      runtime/benches/prioritization_fee_cache.rs
  39. 12 5
      runtime/src/bank/tests.rs
  40. 63 43
      runtime/src/bank_forks.rs
  41. 4 4
      runtime/src/prioritization_fee_cache.rs
  42. 1 1
      runtime/src/root_bank_cache.rs
  43. 4 4
      send-transaction-service/src/send_transaction_service.rs
  44. 2 7
      turbine/benches/cluster_info.rs
  45. 3 4
      turbine/benches/retransmit_stage.rs
  46. 1 1
      turbine/src/broadcast_stage.rs
  47. 1 1
      turbine/src/broadcast_stage/standard_broadcast_run.rs
  48. 1 1
      turbine/src/quic_endpoint.rs
  49. 1 1
      turbine/src/sigverify_shreds.rs
  50. 1 4
      validator/src/admin_rpc_service.rs

Файловите разлики са ограничени, защото са твърде много
+ 167 - 143
Cargo.lock


+ 1 - 1
banking-bench/src/main.rs

@@ -334,7 +334,7 @@ fn main() {
 
     let (replay_vote_sender, _replay_vote_receiver) = unbounded();
     let bank0 = Bank::new_for_benches(&genesis_config);
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+    let bank_forks = BankForks::new_rw_arc(bank0);
     let mut bank = bank_forks.read().unwrap().working_bank();
 
     // set cost tracker limits to MAX so it will not filter out TXs

+ 2 - 2
banks-client/src/lib.rs

@@ -587,7 +587,7 @@ mod tests {
         let block_commitment_cache = Arc::new(RwLock::new(
             BlockCommitmentCache::new_for_tests_with_slots(slot, slot),
         ));
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let bob_pubkey = solana_sdk::pubkey::new_rand();
         let mint_pubkey = genesis.mint_keypair.pubkey();
@@ -626,7 +626,7 @@ mod tests {
         let block_commitment_cache = Arc::new(RwLock::new(
             BlockCommitmentCache::new_for_tests_with_slots(slot, slot),
         ));
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let mint_pubkey = &genesis.mint_keypair.pubkey();
         let bob_pubkey = solana_sdk::pubkey::new_rand();

+ 6 - 6
client-test/tests/client.rs

@@ -132,7 +132,7 @@ fn test_account_subscription() {
     } = create_genesis_config(10_000);
     let bank = Bank::new_for_tests(&genesis_config);
     let blockhash = bank.last_blockhash();
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+    let bank_forks = BankForks::new_rw_arc(bank);
     let bank0 = bank_forks.read().unwrap().get(0).unwrap();
     let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
     bank_forks.write().unwrap().insert(bank1);
@@ -230,7 +230,7 @@ fn test_block_subscription() {
     } = create_genesis_config(10_000);
     let bank = Bank::new_for_tests(&genesis_config);
     let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+    let bank_forks = BankForks::new_rw_arc(bank);
 
     // setup Blockstore
     let ledger_path = get_tmp_ledger_path!();
@@ -338,7 +338,7 @@ fn test_program_subscription() {
     } = create_genesis_config(10_000);
     let bank = Bank::new_for_tests(&genesis_config);
     let blockhash = bank.last_blockhash();
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+    let bank_forks = BankForks::new_rw_arc(bank);
     let bank0 = bank_forks.read().unwrap().get(0).unwrap();
     let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
     bank_forks.write().unwrap().insert(bank1);
@@ -425,7 +425,7 @@ fn test_root_subscription() {
 
     let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
     let bank = Bank::new_for_tests(&genesis_config);
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+    let bank_forks = BankForks::new_rw_arc(bank);
     let bank0 = bank_forks.read().unwrap().get(0).unwrap();
     let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
     bank_forks.write().unwrap().insert(bank1);
@@ -477,7 +477,7 @@ fn test_slot_subscription() {
     let exit = Arc::new(AtomicBool::new(false));
     let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
     let bank = Bank::new_for_tests(&genesis_config);
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+    let bank_forks = BankForks::new_rw_arc(bank);
     let optimistically_confirmed_bank =
         OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
     let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
@@ -553,7 +553,7 @@ async fn test_slot_subscription_async() {
         let exit = Arc::new(AtomicBool::new(false));
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());

+ 2 - 2
core/benches/banking_stage.rs

@@ -55,7 +55,7 @@ use {
     },
     std::{
         iter::repeat_with,
-        sync::{atomic::Ordering, Arc, RwLock},
+        sync::{atomic::Ordering, Arc},
         time::{Duration, Instant},
     },
     test::Bencher,
@@ -219,7 +219,7 @@ fn bench_banking(bencher: &mut Bencher, tx_type: TransactionType) {
     let mut bank = Bank::new_for_benches(&genesis_config);
     // Allow arbitrary transaction processing time for the purposes of this bench
     bank.ns_per_slot = u128::MAX;
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+    let bank_forks = BankForks::new_rw_arc(bank);
     let bank = bank_forks.read().unwrap().get(0).unwrap();
 
     // set cost tracker limits to MAX so it will not filter out TXs

+ 8 - 2
core/benches/consensus.rs

@@ -28,7 +28,10 @@ fn bench_save_tower(bench: &mut Bencher) {
 
     let vote_account_pubkey = &Pubkey::default();
     let node_keypair = Arc::new(Keypair::new());
-    let heaviest_bank = BankForks::new(Bank::default_for_tests()).working_bank();
+    let heaviest_bank = BankForks::new_rw_arc(Bank::default_for_tests())
+        .read()
+        .unwrap()
+        .working_bank();
     let tower_storage = FileTowerStorage::new(dir.path().to_path_buf());
     let tower = Tower::new(
         &node_keypair.pubkey(),
@@ -47,7 +50,10 @@ fn bench_save_tower(bench: &mut Bencher) {
 fn bench_generate_ancestors_descendants(bench: &mut Bencher) {
     let vote_account_pubkey = &Pubkey::default();
     let node_keypair = Arc::new(Keypair::new());
-    let heaviest_bank = BankForks::new(Bank::default_for_tests()).working_bank();
+    let heaviest_bank = BankForks::new_rw_arc(Bank::default_for_tests())
+        .read()
+        .unwrap()
+        .working_bank();
     let mut tower = Tower::new(
         &node_keypair.pubkey(),
         vote_account_pubkey,

+ 5 - 5
core/src/banking_stage.rs

@@ -670,7 +670,7 @@ mod tests {
     fn test_banking_stage_shutdown1() {
         let genesis_config = create_genesis_config(2).genesis_config;
         let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().get(0).unwrap();
         let banking_tracer = BankingTracer::new_disabled();
         let (non_vote_sender, non_vote_receiver) = banking_tracer.create_channel_non_vote();
@@ -722,7 +722,7 @@ mod tests {
         genesis_config.ticks_per_slot = 4;
         let num_extra_ticks = 2;
         let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().get(0).unwrap();
         let start_hash = bank.last_blockhash();
         let banking_tracer = BankingTracer::new_disabled();
@@ -802,7 +802,7 @@ mod tests {
             ..
         } = create_slow_genesis_config(10);
         let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().get(0).unwrap();
         let start_hash = bank.last_blockhash();
         let banking_tracer = BankingTracer::new_disabled();
@@ -974,7 +974,7 @@ mod tests {
             let entry_receiver = {
                 // start a banking_stage to eat verified receiver
                 let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
-                let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+                let bank_forks = BankForks::new_rw_arc(bank);
                 let bank = bank_forks.read().unwrap().get(0).unwrap();
                 let blockstore = Arc::new(
                     Blockstore::open(ledger_path.path())
@@ -1155,7 +1155,7 @@ mod tests {
             ..
         } = create_slow_genesis_config(10000);
         let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().get(0).unwrap();
         let start_hash = bank.last_blockhash();
         let banking_tracer = BankingTracer::new_disabled();

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

@@ -174,7 +174,7 @@ mod tests {
             ..
         } = create_slow_genesis_config(10_000);
         let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().working_bank();
 
         let ledger_path = get_tmp_ledger_path_auto_delete!();

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

@@ -129,7 +129,7 @@ mod tests {
             ..
         } = create_slow_genesis_config(10_000);
         let bank = Bank::new_no_wallclock_throttle_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().working_bank();
 
         let ledger_path = get_tmp_ledger_path_auto_delete!();

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

@@ -307,7 +307,7 @@ mod tests {
         let GenesisConfigInfo { genesis_config, .. } = &genesis_config_info;
 
         let bank: Bank = Bank::new_no_wallclock_throttle_for_tests(genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().working_bank();
 
         let ledger_path = TempDir::new().unwrap();

+ 5 - 5
core/src/cluster_info_vote_listener.rs

@@ -1439,7 +1439,7 @@ mod tests {
             );
         let bank = Bank::new_for_tests(&genesis_config);
         let exit = Arc::new(AtomicBool::new(false));
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().get(0).unwrap();
         let vote_tracker = VoteTracker::default();
         let optimistically_confirmed_bank =
@@ -1556,7 +1556,7 @@ mod tests {
         let bank = Bank::new_for_tests(&genesis_config);
         let vote_tracker = VoteTracker::default();
         let exit = Arc::new(AtomicBool::new(false));
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().get(0).unwrap();
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
@@ -1584,7 +1584,7 @@ mod tests {
         solana_logger::setup();
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = RwLock::new(BankForks::new(bank));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let votes = vec![];
         let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, &bank_forks);
         assert!(vote_txs.is_empty());
@@ -1629,7 +1629,7 @@ mod tests {
                 vec![100; voting_keypairs.len()], // stakes
             );
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = RwLock::new(BankForks::new(bank));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let vote_tx = test_vote_tx(voting_keypairs.first(), hash);
         let votes = vec![vote_tx];
         let (vote_txs, packets) = ClusterInfoVoteListener::verify_votes(votes, &bank_forks);
@@ -1654,7 +1654,7 @@ mod tests {
                 vec![100; voting_keypairs.len()], // stakes
             );
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = RwLock::new(BankForks::new(bank));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let vote_tx = test_vote_tx(voting_keypairs.first(), hash);
         let mut bad_vote = vote_tx.clone();
         bad_vote.signatures[0] = Signature::default();

+ 2 - 1
core/src/commitment_service.rs

@@ -509,7 +509,8 @@ mod tests {
         );
 
         let bank0 = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks = BankForks::new(bank0);
+        let bank_forks = BankForks::new_rw_arc(bank0);
+        let mut bank_forks = bank_forks.write().unwrap();
 
         // Fill bank_forks with banks with votes landing in the next slot
         // Create enough banks such that vote account will root slots 0 and 1

+ 2 - 1
core/src/consensus/heaviest_subtree_fork_choice.rs

@@ -244,7 +244,8 @@ impl HeaviestSubtreeForkChoice {
         heaviest_subtree_fork_choice
     }
 
-    pub fn new_from_bank_forks(bank_forks: &BankForks) -> Self {
+    pub fn new_from_bank_forks(bank_forks: Arc<RwLock<BankForks>>) -> Self {
+        let bank_forks = bank_forks.read().unwrap();
         let mut frozen_banks: Vec<_> = bank_forks.frozen_banks().values().cloned().collect();
 
         frozen_banks.sort_by_key(|bank| bank.slot());

+ 1 - 1
core/src/repair/ancestor_hashes_service.rs

@@ -1928,7 +1928,7 @@ mod test {
     #[test]
     fn test_verify_and_process_ancestor_responses_invalid_packet() {
         let bank0 = Bank::default_for_tests();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+        let bank_forks = BankForks::new_rw_arc(bank0);
 
         let ManageAncestorHashesState {
             ancestor_hashes_request_statuses,

+ 1 - 1
core/src/repair/quic_endpoint.rs

@@ -736,7 +736,7 @@ mod tests {
             let GenesisConfigInfo { genesis_config, .. } =
                 create_genesis_config(/*mint_lamports:*/ 100_000);
             let bank = Bank::new_for_tests(&genesis_config);
-            Arc::new(RwLock::new(BankForks::new(bank)))
+            BankForks::new_rw_arc(bank)
         };
         let (endpoints, senders, tasks): (Vec<_>, Vec<_>, Vec<_>) = multiunzip(
             keypairs

+ 2 - 2
core/src/repair/repair_service.rs

@@ -1202,7 +1202,7 @@ mod test {
     pub fn test_generate_and_send_duplicate_repairs() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let blockstore_path = get_tmp_ledger_path!();
         let blockstore = Blockstore::open(&blockstore_path).unwrap();
         let cluster_slots = ClusterSlots::default();
@@ -1301,7 +1301,7 @@ mod test {
     pub fn test_update_duplicate_slot_repair_addr() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let dummy_addr = Some((
             Pubkey::default(),
             UdpSocket::bind("0.0.0.0:0").unwrap().local_addr().unwrap(),

+ 5 - 5
core/src/repair/serve_repair.rs

@@ -1561,7 +1561,7 @@ mod tests {
     fn test_serialize_deserialize_signed_request() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let cluster_info = Arc::new(new_test_cluster_info());
         let serve_repair = ServeRepair::new(
             cluster_info.clone(),
@@ -1611,7 +1611,7 @@ mod tests {
 
         let mut bank = Bank::new_for_tests(&genesis_config);
         bank.feature_set = Arc::new(FeatureSet::all_enabled());
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let serve_repair = ServeRepair::new(
             cluster_info,
             bank_forks,
@@ -1647,7 +1647,7 @@ mod tests {
     fn test_map_requests_signed() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let cluster_info = Arc::new(new_test_cluster_info());
         let serve_repair = ServeRepair::new(
             cluster_info.clone(),
@@ -1976,7 +1976,7 @@ mod tests {
     fn window_index_request() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let cluster_slots = ClusterSlots::default();
         let cluster_info = Arc::new(new_test_cluster_info());
         let serve_repair = ServeRepair::new(
@@ -2318,7 +2318,7 @@ mod tests {
     fn test_repair_with_repair_validators() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let cluster_slots = ClusterSlots::default();
         let cluster_info = Arc::new(new_test_cluster_info());
         let me = cluster_info.my_contact_info();

+ 23 - 15
core/src/replay_stage.rs

@@ -4360,7 +4360,7 @@ pub(crate) mod tests {
     fn test_handle_new_root() {
         let genesis_config = create_genesis_config(10_000).genesis_config;
         let bank0 = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+        let bank_forks = BankForks::new_rw_arc(bank0);
 
         let root = 3;
         let root_bank = Bank::new_from_parent(
@@ -4446,7 +4446,7 @@ pub(crate) mod tests {
     fn test_handle_new_root_ahead_of_highest_super_majority_root() {
         let genesis_config = create_genesis_config(10_000).genesis_config;
         let bank0 = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+        let bank_forks = BankForks::new_rw_arc(bank0);
         let confirmed_root = 1;
         let fork = 2;
         let bank1 = Bank::new_from_parent(
@@ -4849,7 +4849,7 @@ pub(crate) mod tests {
         }
         bank0.freeze();
         let arc_bank0 = Arc::new(bank0);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new_from_banks(&[arc_bank0], 0)));
+        let bank_forks = BankForks::new_from_banks(&[arc_bank0], 0);
 
         let exit = Arc::new(AtomicBool::new(false));
         let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
@@ -5028,7 +5028,7 @@ pub(crate) mod tests {
             vote_simulator::initialize_state(&keypairs, 10_000);
         let mut latest_validator_votes_for_frozen_banks =
             LatestValidatorVotesForFrozenBanks::default();
-        let bank0 = bank_forks.get(0).unwrap();
+        let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let my_keypairs = keypairs.get(&my_node_pubkey).unwrap();
         let vote_tx = vote_transaction::new_vote_transaction(
             vec![0],
@@ -5040,7 +5040,6 @@ pub(crate) mod tests {
             None,
         );
 
-        let bank_forks = RwLock::new(bank_forks);
         let bank1 = Bank::new_from_parent(bank0.clone(), &my_node_pubkey, 1);
         bank1.process_transaction(&vote_tx).unwrap();
         bank1.freeze();
@@ -5373,7 +5372,7 @@ pub(crate) mod tests {
     ) {
         let stake = 10_000;
         let (bank_forks, _, _) = vote_simulator::initialize_state(all_keypairs, stake);
-        let root_bank = bank_forks.root_bank();
+        let root_bank = bank_forks.read().unwrap().root_bank();
         let mut propagated_stats = PropagatedStats {
             total_epoch_stake: stake * all_keypairs.len() as u64,
             ..PropagatedStats::default()
@@ -5487,8 +5486,9 @@ pub(crate) mod tests {
         let vote_pubkey = vote_keypairs.vote_keypair.pubkey();
         let keypairs: HashMap<_, _> = vec![(node_pubkey, vote_keypairs)].into_iter().collect();
         let stake = 10_000;
-        let (mut bank_forks, mut progress_map, _) =
+        let (bank_forks_arc, mut progress_map, _) =
             vote_simulator::initialize_state(&keypairs, stake);
+        let mut bank_forks = bank_forks_arc.write().unwrap();
 
         let bank0 = bank_forks.get(0).unwrap();
         bank_forks.insert(Bank::new_from_parent(bank0.clone(), &Pubkey::default(), 9));
@@ -5530,12 +5530,14 @@ pub(crate) mod tests {
         // runs in `update_propagation_status`
         assert!(!progress_map.get_leader_propagation_slot_must_exist(10).0);
 
+        drop(bank_forks);
+
         let vote_tracker = VoteTracker::default();
         vote_tracker.insert_vote(10, vote_pubkey);
         ReplayStage::update_propagation_status(
             &mut progress_map,
             10,
-            &RwLock::new(bank_forks),
+            &bank_forks_arc,
             &vote_tracker,
             &ClusterSlots::default(),
         );
@@ -5579,8 +5581,9 @@ pub(crate) mod tests {
             .collect();
 
         let stake_per_validator = 10_000;
-        let (mut bank_forks, mut progress_map, _) =
+        let (bank_forks_arc, mut progress_map, _) =
             vote_simulator::initialize_state(&keypairs, stake_per_validator);
+        let mut bank_forks = bank_forks_arc.write().unwrap();
         progress_map
             .get_propagated_stats_mut(0)
             .unwrap()
@@ -5621,12 +5624,14 @@ pub(crate) mod tests {
             vote_tracker.insert_vote(10, *vote_pubkey);
         }
 
+        drop(bank_forks);
+
         // The last bank should reach propagation threshold, and propagate it all
         // the way back through earlier leader banks
         ReplayStage::update_propagation_status(
             &mut progress_map,
             10,
-            &RwLock::new(bank_forks),
+            &bank_forks_arc,
             &vote_tracker,
             &ClusterSlots::default(),
         );
@@ -5659,8 +5664,9 @@ pub(crate) mod tests {
             .collect();
 
         let stake_per_validator = 10_000;
-        let (mut bank_forks, mut progress_map, _) =
+        let (bank_forks_arc, mut progress_map, _) =
             vote_simulator::initialize_state(&keypairs, stake_per_validator);
+        let mut bank_forks = bank_forks_arc.write().unwrap();
         progress_map
             .get_propagated_stats_mut(0)
             .unwrap()
@@ -5706,12 +5712,13 @@ pub(crate) mod tests {
         // Insert a new vote
         vote_tracker.insert_vote(10, vote_pubkeys[2]);
 
+        drop(bank_forks);
         // The last bank should reach propagation threshold, and propagate it all
         // the way back through earlier leader banks
         ReplayStage::update_propagation_status(
             &mut progress_map,
             10,
-            &RwLock::new(bank_forks),
+            &bank_forks_arc,
             &vote_tracker,
             &ClusterSlots::default(),
         );
@@ -5817,7 +5824,8 @@ pub(crate) mod tests {
         let bank0 = Bank::new_for_tests(&genesis_config::create_genesis_config(10000).0);
         let parent_slot_bank =
             Bank::new_from_parent(Arc::new(bank0), &Pubkey::default(), parent_slot);
-        let mut bank_forks = BankForks::new(parent_slot_bank);
+        let bank_forks = BankForks::new_rw_arc(parent_slot_bank);
+        let mut bank_forks = bank_forks.write().unwrap();
         let bank5 =
             Bank::new_from_parent(bank_forks.get(parent_slot).unwrap(), &Pubkey::default(), 5);
         bank_forks.insert(bank5);
@@ -6367,7 +6375,7 @@ pub(crate) mod tests {
             &vote_tracker,
             &ClusterSlots::default(),
             &bank_forks,
-            &mut HeaviestSubtreeForkChoice::new_from_bank_forks(&bank_forks.read().unwrap()),
+            &mut HeaviestSubtreeForkChoice::new_from_bank_forks(bank_forks.clone()),
             &mut LatestValidatorVotesForFrozenBanks::default(),
         );
 
@@ -8133,7 +8141,7 @@ pub(crate) mod tests {
         let in_vote_only_mode = AtomicBool::new(false);
         let genesis_config = create_genesis_config(10_000).genesis_config;
         let bank0 = Bank::new_for_tests(&genesis_config);
-        let bank_forks = RwLock::new(BankForks::new(bank0));
+        let bank_forks = BankForks::new_rw_arc(bank0);
         ReplayStage::check_for_vote_only_mode(1000, 0, &in_vote_only_mode, &bank_forks);
         assert!(in_vote_only_mode.load(Ordering::Relaxed));
         ReplayStage::check_for_vote_only_mode(10, 0, &in_vote_only_mode, &bank_forks);

+ 2 - 3
core/src/tvu.rs

@@ -401,7 +401,7 @@ pub mod tests {
         let starting_balance = 10_000;
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(starting_balance);
 
-        let bank_forks = BankForks::new(Bank::new_for_tests(&genesis_config));
+        let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
 
         let keypair = Arc::new(Keypair::new());
         let (turbine_quic_endpoint_sender, _turbine_quic_endpoint_receiver) =
@@ -423,7 +423,7 @@ pub mod tests {
         } = Blockstore::open_with_signal(&blockstore_path, BlockstoreOptions::default())
             .expect("Expected to successfully open ledger");
         let blockstore = Arc::new(blockstore);
-        let bank = bank_forks.working_bank();
+        let bank = bank_forks.read().unwrap().working_bank();
         let (exit, poh_recorder, poh_service, _entry_receiver) =
             create_test_recorder(bank.clone(), blockstore.clone(), None, None);
         let vote_keypair = Keypair::new();
@@ -435,7 +435,6 @@ pub mod tests {
         let (replay_vote_sender, _replay_vote_receiver) = unbounded();
         let (completed_data_sets_sender, _completed_data_sets_receiver) = unbounded();
         let (_, gossip_confirmed_slots_receiver) = unbounded();
-        let bank_forks = Arc::new(RwLock::new(bank_forks));
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
         let ignored_prioritization_fee_cache = Arc::new(PrioritizationFeeCache::new(0u64));

+ 3 - 3
core/src/validator.rs

@@ -2584,7 +2584,7 @@ mod tests {
         );
 
         let (genesis_config, _mint_keypair) = create_genesis_config(1);
-        let bank_forks = RwLock::new(BankForks::new(Bank::new_for_tests(&genesis_config)));
+        let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
         let mut config = ValidatorConfig::default_for_test();
         let rpc_override_health_check = Arc::new(AtomicBool::new(false));
         let start_progress = Arc::new(RwLock::new(ValidatorStartProgress::default()));
@@ -2614,11 +2614,11 @@ mod tests {
         );
 
         // bank=1, wait=0, should pass, bank is past the wait slot
-        let bank_forks = RwLock::new(BankForks::new(Bank::new_from_parent(
+        let bank_forks = BankForks::new_rw_arc(Bank::new_from_parent(
             bank_forks.read().unwrap().root_bank(),
             &Pubkey::default(),
             1,
-        )));
+        ));
         config.wait_for_supermajority = Some(0);
         assert!(!wait_for_supermajority(
             &config,

+ 11 - 5
core/src/vote_simulator.rs

@@ -57,7 +57,7 @@ impl VoteSimulator {
             validator_keypairs,
             node_pubkeys,
             vote_pubkeys,
-            bank_forks: Arc::new(RwLock::new(bank_forks)),
+            bank_forks,
             progress,
             heaviest_subtree_fork_choice,
             latest_validator_votes_for_frozen_banks: LatestValidatorVotesForFrozenBanks::default(),
@@ -296,13 +296,14 @@ impl VoteSimulator {
         false
     }
 
+    #[allow(clippy::type_complexity)]
     fn init_state(
         num_keypairs: usize,
     ) -> (
         HashMap<Pubkey, ValidatorVoteKeypairs>,
         Vec<Pubkey>,
         Vec<Pubkey>,
-        BankForks,
+        Arc<RwLock<BankForks>>,
         ProgressMap,
         HeaviestSubtreeForkChoice,
     ) {
@@ -338,7 +339,11 @@ impl VoteSimulator {
 pub fn initialize_state(
     validator_keypairs_map: &HashMap<Pubkey, ValidatorVoteKeypairs>,
     stake: u64,
-) -> (BankForks, ProgressMap, HeaviestSubtreeForkChoice) {
+) -> (
+    Arc<RwLock<BankForks>>,
+    ProgressMap,
+    HeaviestSubtreeForkChoice,
+) {
     let validator_keypairs: Vec<_> = validator_keypairs_map.values().collect();
     let GenesisConfigInfo {
         mut genesis_config,
@@ -366,7 +371,8 @@ pub fn initialize_state(
         0,
         ForkProgress::new_from_bank(&bank0, bank0.collector_id(), &Pubkey::default(), None, 0, 0),
     );
-    let bank_forks = BankForks::new(bank0);
-    let heaviest_subtree_fork_choice = HeaviestSubtreeForkChoice::new_from_bank_forks(&bank_forks);
+    let bank_forks = BankForks::new_rw_arc(bank0);
+    let heaviest_subtree_fork_choice =
+        HeaviestSubtreeForkChoice::new_from_bank_forks(bank_forks.clone());
     (bank_forks, progress, heaviest_subtree_fork_choice)
 }

+ 17 - 8
core/tests/epoch_accounts_hash.rs

@@ -116,13 +116,18 @@ impl TestEnvironment {
             ..snapshot_config
         };
 
-        let mut bank_forks = BankForks::new(Bank::new_for_tests_with_config(
+        let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests_with_config(
             &genesis_config_info.genesis_config,
             BankTestConfig::default(),
         ));
-        bank_forks.set_snapshot_config(Some(snapshot_config.clone()));
-        bank_forks.set_accounts_hash_interval_slots(Self::ACCOUNTS_HASH_INTERVAL);
-        let bank_forks = Arc::new(RwLock::new(bank_forks));
+        bank_forks
+            .write()
+            .unwrap()
+            .set_snapshot_config(Some(snapshot_config.clone()));
+        bank_forks
+            .write()
+            .unwrap()
+            .set_accounts_hash_interval_slots(Self::ACCOUNTS_HASH_INTERVAL);
 
         let exit = Arc::new(AtomicBool::new(false));
         let node_id = Arc::new(Keypair::new());
@@ -264,7 +269,7 @@ fn test_epoch_accounts_hash_basic(test_environment: TestEnvironment) {
     const NUM_EPOCHS_TO_TEST: u64 = 2;
     const SET_ROOT_INTERVAL: Slot = 3;
 
-    let bank_forks = &test_environment.bank_forks;
+    let bank_forks = test_environment.bank_forks.clone();
 
     let mut expected_epoch_accounts_hash = None;
 
@@ -299,6 +304,7 @@ fn test_epoch_accounts_hash_basic(test_environment: TestEnvironment) {
         // Set roots so that ABS requests are sent (this is what requests EAH calculations)
         if bank.slot().checked_rem(SET_ROOT_INTERVAL).unwrap() == 0 {
             trace!("rooting bank {}", bank.slot());
+            bank_forks.read().unwrap().prune_program_cache(bank.slot());
             bank_forks.write().unwrap().set_root(
                 bank.slot(),
                 &test_environment
@@ -379,7 +385,7 @@ fn test_snapshots_have_expected_epoch_accounts_hash() {
 
     let test_environment =
         TestEnvironment::new_with_snapshots(FULL_SNAPSHOT_INTERVAL, FULL_SNAPSHOT_INTERVAL);
-    let bank_forks = &test_environment.bank_forks;
+    let bank_forks = test_environment.bank_forks.clone();
 
     let slots_per_epoch = test_environment
         .genesis_config_info
@@ -411,6 +417,7 @@ fn test_snapshots_have_expected_epoch_accounts_hash() {
 
         // Root every bank.  This is what a normal validator does as well.
         // `set_root()` is also what requests snapshots and EAH calculations.
+        bank_forks.read().unwrap().prune_program_cache(bank.slot());
         bank_forks.write().unwrap().set_root(
             bank.slot(),
             &test_environment
@@ -496,7 +503,7 @@ fn test_background_services_request_handling_for_epoch_accounts_hash() {
 
     let test_environment =
         TestEnvironment::new_with_snapshots(FULL_SNAPSHOT_INTERVAL, FULL_SNAPSHOT_INTERVAL);
-    let bank_forks = &test_environment.bank_forks;
+    let bank_forks = test_environment.bank_forks.clone();
     let snapshot_config = &test_environment.snapshot_config;
 
     let slots_per_epoch = test_environment
@@ -534,6 +541,7 @@ fn test_background_services_request_handling_for_epoch_accounts_hash() {
 
         if bank.block_height() == set_root_slot {
             info!("Calling set_root() on bank {}...", bank.slot());
+            bank_forks.read().unwrap().prune_program_cache(bank.slot());
             bank_forks.write().unwrap().set_root(
                 bank.slot(),
                 &test_environment
@@ -577,7 +585,7 @@ fn test_epoch_accounts_hash_and_warping() {
     solana_logger::setup();
 
     let test_environment = TestEnvironment::new();
-    let bank_forks = &test_environment.bank_forks;
+    let bank_forks = test_environment.bank_forks.clone();
     let bank = bank_forks.read().unwrap().working_bank();
     let epoch_schedule = test_environment
         .genesis_config_info
@@ -590,6 +598,7 @@ fn test_epoch_accounts_hash_and_warping() {
     let eah_stop_slot_in_next_epoch =
         epoch_schedule.get_first_slot_in_epoch(bank.epoch() + 1) + eah_stop_offset;
     // have to set root here so that we can flush the write cache
+    bank_forks.read().unwrap().prune_program_cache(bank.slot());
     bank_forks.write().unwrap().set_root(
         bank.slot(),
         &test_environment

+ 53 - 29
core/tests/snapshots.rs

@@ -66,7 +66,7 @@ use {
 };
 
 struct SnapshotTestConfig {
-    bank_forks: BankForks,
+    bank_forks: Arc<RwLock<BankForks>>,
     genesis_config_info: GenesisConfigInfo,
     snapshot_config: SnapshotConfig,
     incremental_snapshot_archives_dir: TempDir,
@@ -109,7 +109,8 @@ impl SnapshotTestConfig {
         );
         bank0.freeze();
         bank0.set_startup_verification_complete();
-        let mut bank_forks = BankForks::new(bank0);
+        let bank_forks_arc = BankForks::new_rw_arc(bank0);
+        let mut bank_forks = bank_forks_arc.write().unwrap();
         bank_forks.accounts_hash_interval_slots = accounts_hash_interval_slots;
 
         let snapshot_config = SnapshotConfig {
@@ -125,7 +126,7 @@ impl SnapshotTestConfig {
         };
         bank_forks.set_snapshot_config(Some(snapshot_config.clone()));
         SnapshotTestConfig {
-            bank_forks,
+            bank_forks: bank_forks_arc.clone(),
             genesis_config_info,
             snapshot_config,
             incremental_snapshot_archives_dir,
@@ -138,11 +139,12 @@ impl SnapshotTestConfig {
 }
 
 fn restore_from_snapshot(
-    old_bank_forks: &BankForks,
+    old_bank_forks: Arc<RwLock<BankForks>>,
     old_last_slot: Slot,
     old_genesis_config: &GenesisConfig,
     account_paths: &[PathBuf],
 ) {
+    let old_bank_forks = old_bank_forks.read().unwrap();
     let snapshot_config = old_bank_forks.snapshot_config.as_ref().unwrap();
     let old_last_bank = old_bank_forks.get(old_last_slot).unwrap();
 
@@ -198,7 +200,7 @@ fn run_bank_forks_snapshot_n<F>(
 {
     solana_logger::setup();
     // Set up snapshotting config
-    let mut snapshot_test_config = SnapshotTestConfig::new(
+    let snapshot_test_config = SnapshotTestConfig::new(
         snapshot_version,
         cluster_type,
         set_root_interval,
@@ -206,7 +208,7 @@ fn run_bank_forks_snapshot_n<F>(
         DISABLED_SNAPSHOT_ARCHIVE_INTERVAL,
     );
 
-    let bank_forks = &mut snapshot_test_config.bank_forks;
+    let bank_forks = snapshot_test_config.bank_forks.clone();
     let mint_keypair = &snapshot_test_config.genesis_config_info.mint_keypair;
 
     let (accounts_package_sender, _accounts_package_receiver) = crossbeam_channel::unbounded();
@@ -219,16 +221,22 @@ fn run_bank_forks_snapshot_n<F>(
         accounts_package_sender,
     };
     for slot in 1..=last_slot {
+        let mut bank_forks_w = bank_forks.write().unwrap();
         let mut bank =
-            Bank::new_from_parent(bank_forks[slot - 1].clone(), &Pubkey::default(), slot);
+            Bank::new_from_parent(bank_forks_w[slot - 1].clone(), &Pubkey::default(), slot);
         f(&mut bank, mint_keypair);
-        let bank = bank_forks.insert(bank);
+        let bank = bank_forks_w.insert(bank);
+        drop(bank_forks_w);
         // Set root to make sure we don't end up with too many account storage entries
         // and to allow snapshotting of bank and the purging logic on status_cache to
         // kick in
         if slot % set_root_interval == 0 || slot == last_slot {
             // set_root should send a snapshot request
-            bank_forks.set_root(bank.slot(), &request_sender, None);
+            bank_forks.read().unwrap().prune_program_cache(bank.slot());
+            bank_forks
+                .write()
+                .unwrap()
+                .set_root(bank.slot(), &request_sender, None);
             snapshot_request_handler.handle_snapshot_requests(
                 false,
                 0,
@@ -239,7 +247,7 @@ fn run_bank_forks_snapshot_n<F>(
     }
 
     // Generate a snapshot package for last bank
-    let last_bank = bank_forks.get(last_slot).unwrap();
+    let last_bank = bank_forks.read().unwrap().get(last_slot).unwrap();
     let snapshot_config = &snapshot_test_config.snapshot_config;
     let bank_snapshots_dir = &snapshot_config.bank_snapshots_dir;
     let last_bank_snapshot_info = snapshot_utils::get_highest_bank_snapshot_pre(bank_snapshots_dir)
@@ -278,7 +286,12 @@ fn run_bank_forks_snapshot_n<F>(
     let (_tmp_dir, temporary_accounts_dir) = create_tmp_accounts_dir_for_tests();
     let account_paths = &[temporary_accounts_dir];
     let genesis_config = &snapshot_test_config.genesis_config_info.genesis_config;
-    restore_from_snapshot(bank_forks, last_slot, genesis_config, account_paths);
+    restore_from_snapshot(
+        snapshot_test_config.bank_forks.clone(),
+        last_slot,
+        genesis_config,
+        account_paths,
+    );
 }
 
 #[test_case(V1_2_0, Development)]
@@ -331,7 +344,7 @@ fn test_concurrent_snapshot_packaging(
     const MAX_BANK_SNAPSHOTS_TO_RETAIN: usize = 8;
 
     // Set up snapshotting config
-    let mut snapshot_test_config = SnapshotTestConfig::new(
+    let snapshot_test_config = SnapshotTestConfig::new(
         snapshot_version,
         cluster_type,
         1,
@@ -339,7 +352,7 @@ fn test_concurrent_snapshot_packaging(
         DISABLED_SNAPSHOT_ARCHIVE_INTERVAL,
     );
 
-    let bank_forks = &mut snapshot_test_config.bank_forks;
+    let mut bank_forks = snapshot_test_config.bank_forks.write().unwrap();
     let snapshot_config = &snapshot_test_config.snapshot_config;
     let bank_snapshots_dir = &snapshot_config.bank_snapshots_dir;
     let full_snapshot_archives_dir = &snapshot_config.full_snapshot_archives_dir;
@@ -586,24 +599,31 @@ fn test_slots_to_snapshot(snapshot_version: SnapshotVersion, cluster_type: Clust
     for add_root_interval in &[1, 3, 9] {
         let (snapshot_sender, _snapshot_receiver) = unbounded();
         // Make sure this test never clears bank.slots_since_snapshot
-        let mut snapshot_test_config = SnapshotTestConfig::new(
+        let snapshot_test_config = SnapshotTestConfig::new(
             snapshot_version,
             cluster_type,
             (*add_root_interval * num_set_roots * 2) as Slot,
             (*add_root_interval * num_set_roots * 2) as Slot,
             DISABLED_SNAPSHOT_ARCHIVE_INTERVAL,
         );
-        let mut current_bank = snapshot_test_config.bank_forks[0].clone();
+        let bank_forks = snapshot_test_config.bank_forks.clone();
+        let bank_forks_r = bank_forks.read().unwrap();
+        let mut current_bank = bank_forks_r[0].clone();
+        drop(bank_forks_r);
         let request_sender = AbsRequestSender::new(snapshot_sender);
         for _ in 0..num_set_roots {
             for _ in 0..*add_root_interval {
                 let new_slot = current_bank.slot() + 1;
                 let new_bank = Bank::new_from_parent(current_bank, &Pubkey::default(), new_slot);
-                snapshot_test_config.bank_forks.insert(new_bank);
-                current_bank = snapshot_test_config.bank_forks[new_slot].clone();
+                current_bank = bank_forks.write().unwrap().insert(new_bank).clone();
             }
-            snapshot_test_config
-                .bank_forks
+            bank_forks
+                .read()
+                .unwrap()
+                .prune_program_cache(current_bank.slot());
+            bank_forks
+                .write()
+                .unwrap()
                 .set_root(current_bank.slot(), &request_sender, None);
 
             // Since the accounts background services are not runnning, EpochAccountsHash
@@ -629,10 +649,10 @@ fn test_slots_to_snapshot(snapshot_version: SnapshotVersion, cluster_type: Clust
         let expected_slots_to_snapshot =
             num_old_slots as u64..=num_set_roots as u64 * *add_root_interval as u64;
 
-        let slots_to_snapshot = snapshot_test_config
-            .bank_forks
-            .get(snapshot_test_config.bank_forks.root())
+        let slots_to_snapshot = bank_forks
+            .read()
             .unwrap()
+            .root_bank()
             .status_cache
             .read()
             .unwrap()
@@ -704,7 +724,7 @@ fn test_bank_forks_incremental_snapshot(
     info!("Running bank forks incremental snapshot test, full snapshot interval: {} slots, incremental snapshot interval: {} slots, last slot: {}, set root interval: {} slots",
               FULL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS, INCREMENTAL_SNAPSHOT_ARCHIVE_INTERVAL_SLOTS, LAST_SLOT, SET_ROOT_INTERVAL);
 
-    let mut snapshot_test_config = SnapshotTestConfig::new(
+    let snapshot_test_config = SnapshotTestConfig::new(
         snapshot_version,
         cluster_type,
         SET_ROOT_INTERVAL,
@@ -714,7 +734,7 @@ fn test_bank_forks_incremental_snapshot(
     trace!("SnapshotTestConfig:\naccounts_dir: {}\nbank_snapshots_dir: {}\nfull_snapshot_archives_dir: {}\nincremental_snapshot_archives_dir: {}",
             snapshot_test_config.accounts_dir.display(), snapshot_test_config.bank_snapshots_dir.path().display(), snapshot_test_config.full_snapshot_archives_dir.path().display(), snapshot_test_config.incremental_snapshot_archives_dir.path().display());
 
-    let bank_forks = &mut snapshot_test_config.bank_forks;
+    let bank_forks = snapshot_test_config.bank_forks.clone();
     let mint_keypair = &snapshot_test_config.genesis_config_info.mint_keypair;
 
     let (accounts_package_sender, _accounts_package_receiver) = crossbeam_channel::unbounded();
@@ -731,8 +751,8 @@ fn test_bank_forks_incremental_snapshot(
     for slot in 1..=LAST_SLOT {
         // Make a new bank and perform some transactions
         let bank = {
-            let bank =
-                Bank::new_from_parent(bank_forks[slot - 1].clone(), &Pubkey::default(), slot);
+            let parent = bank_forks.read().unwrap().get(slot - 1).unwrap();
+            let bank = Bank::new_from_parent(parent, &Pubkey::default(), slot);
 
             let key = solana_sdk::pubkey::new_rand();
             let tx = system_transaction::transfer(mint_keypair, &key, 1, bank.last_blockhash());
@@ -746,7 +766,7 @@ fn test_bank_forks_incremental_snapshot(
                 bank.register_tick(&Hash::new_unique());
             }
 
-            bank_forks.insert(bank)
+            bank_forks.write().unwrap().insert(bank)
         };
 
         // Set root to make sure we don't end up with too many account storage entries
@@ -754,7 +774,11 @@ fn test_bank_forks_incremental_snapshot(
         // kick in
         if slot % SET_ROOT_INTERVAL == 0 {
             // set_root sends a snapshot request
-            bank_forks.set_root(bank.slot(), &request_sender, None);
+            bank_forks.read().unwrap().prune_program_cache(bank.slot());
+            bank_forks
+                .write()
+                .unwrap()
+                .set_root(bank.slot(), &request_sender, None);
             snapshot_request_handler.handle_snapshot_requests(
                 false,
                 0,
@@ -964,7 +988,7 @@ fn test_snapshots_with_background_services(
     let (accounts_package_sender, accounts_package_receiver) = unbounded();
     let (snapshot_package_sender, snapshot_package_receiver) = unbounded();
 
-    let bank_forks = Arc::new(RwLock::new(snapshot_test_config.bank_forks));
+    let bank_forks = snapshot_test_config.bank_forks.clone();
     bank_forks
         .read()
         .unwrap()

+ 7 - 11
gossip/src/duplicate_shred_handler.rs

@@ -271,15 +271,12 @@ mod tests {
         let my_pubkey = my_keypair.pubkey();
         let genesis_config_info = create_genesis_config_with_leader(10_000, &my_pubkey, 10_000);
         let GenesisConfigInfo { genesis_config, .. } = genesis_config_info;
-        let bank_forks = BankForks::new(Bank::new_for_tests(&genesis_config));
+        let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
         let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(
-            &bank_forks.working_bank(),
+            &bank_forks.read().unwrap().working_bank(),
         ));
-        let mut duplicate_shred_handler = DuplicateShredHandler::new(
-            blockstore.clone(),
-            leader_schedule_cache,
-            Arc::new(RwLock::new(bank_forks)),
-        );
+        let mut duplicate_shred_handler =
+            DuplicateShredHandler::new(blockstore.clone(), leader_schedule_cache, bank_forks);
         let chunks = create_duplicate_proof(
             my_keypair.clone(),
             None,
@@ -340,13 +337,12 @@ mod tests {
         let my_pubkey = my_keypair.pubkey();
         let genesis_config_info = create_genesis_config_with_leader(10_000, &my_pubkey, 10_000);
         let GenesisConfigInfo { genesis_config, .. } = genesis_config_info;
-        let bank_forks = BankForks::new(Bank::new_for_tests(&genesis_config));
+        let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
         let leader_schedule_cache = Arc::new(LeaderScheduleCache::new_from_bank(
-            &bank_forks.working_bank(),
+            &bank_forks.read().unwrap().working_bank(),
         ));
-        let bank_forks_ptr = Arc::new(RwLock::new(bank_forks));
         let mut duplicate_shred_handler =
-            DuplicateShredHandler::new(blockstore.clone(), leader_schedule_cache, bank_forks_ptr);
+            DuplicateShredHandler::new(blockstore.clone(), leader_schedule_cache, bank_forks);
         let start_slot: Slot = 1;
 
         // This proof will not be accepted because num_chunks is too large.

+ 1 - 1
gossip/tests/gossip.rs

@@ -309,7 +309,7 @@ pub fn cluster_info_scale() {
         vec![100; vote_keypairs.len()],
     );
     let bank0 = Bank::new_for_tests(&genesis_config_info.genesis_config);
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+    let bank_forks = BankForks::new_rw_arc(bank0);
 
     let nodes: Vec<_> = vote_keypairs
         .into_iter()

+ 1 - 13
ledger/src/bank_forks_utils.rs

@@ -189,15 +189,6 @@ pub fn load_bank_forks(
             (bank_forks, None)
         };
 
-    bank_forks
-        .read()
-        .expect("Failed to read lock the bank forks")
-        .root_bank()
-        .loaded_programs_cache
-        .write()
-        .expect("Failed to write lock the program cache")
-        .set_fork_graph(bank_forks.clone());
-
     let mut leader_schedule_cache =
         LeaderScheduleCache::new_from_bank(&bank_forks.read().unwrap().root_bank());
     if process_options.full_leader_cache {
@@ -367,8 +358,5 @@ fn bank_forks_from_snapshot(
         incremental: incremental_snapshot_hash,
     };
 
-    (
-        Arc::new(RwLock::new(BankForks::new(bank))),
-        starting_snapshot_hashes,
-    )
+    (BankForks::new_rw_arc(bank), starting_snapshot_hashes)
 }

+ 9 - 6
ledger/src/blockstore_processor.rs

@@ -715,7 +715,7 @@ pub(crate) fn process_blockstore_for_bank_0(
         accounts_update_notifier,
         exit,
     );
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank0)));
+    let bank_forks = BankForks::new_rw_arc(bank0);
 
     info!("Processing ledger for slot 0...");
     process_bank_0(
@@ -3559,8 +3559,8 @@ pub mod tests {
         blockstore.set_roots([3, 5].iter()).unwrap();
 
         // Set up bank1
-        let mut bank_forks = BankForks::new(Bank::new_for_tests(&genesis_config));
-        let bank0 = bank_forks.get(0).unwrap();
+        let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
+        let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let opts = ProcessOptions {
             run_verification: true,
             accounts_db_test_hash_calculation: true,
@@ -3569,7 +3569,11 @@ pub mod tests {
         let recyclers = VerifyRecyclers::default();
         process_bank_0(&bank0, &blockstore, &opts, &recyclers, None, None);
         let bank0_last_blockhash = bank0.last_blockhash();
-        let bank1 = bank_forks.insert(Bank::new_from_parent(bank0, &Pubkey::default(), 1));
+        let bank1 =
+            bank_forks
+                .write()
+                .unwrap()
+                .insert(Bank::new_from_parent(bank0, &Pubkey::default(), 1));
         confirm_full_slot(
             &blockstore,
             &bank1,
@@ -3582,7 +3586,7 @@ pub mod tests {
             &mut ExecuteTimings::default(),
         )
         .unwrap();
-        bank_forks.set_root(
+        bank_forks.write().unwrap().set_root(
             1,
             &solana_runtime::accounts_background_service::AbsRequestSender::default(),
             None,
@@ -3591,7 +3595,6 @@ pub mod tests {
         let leader_schedule_cache = LeaderScheduleCache::new_from_bank(&bank1);
 
         // Test process_blockstore_from_root() from slot 1 onwards
-        let bank_forks = RwLock::new(bank_forks);
         process_blockstore_from_root(
             &blockstore,
             &bank_forks,

+ 1 - 1
program-runtime/src/loaded_programs.rs

@@ -456,7 +456,7 @@ pub struct LoadedPrograms<FG: ForkGraph> {
     /// Environments of the current epoch
     pub environments: ProgramRuntimeEnvironments,
     pub stats: Stats,
-    fork_graph: Option<Arc<RwLock<FG>>>,
+    pub fork_graph: Option<Arc<RwLock<FG>>>,
 }
 
 impl<FG: ForkGraph> Default for LoadedPrograms<FG> {

+ 1 - 1
program-test/src/lib.rs

@@ -847,7 +847,7 @@ impl ProgramTest {
         };
         let slot = bank.slot();
         let last_blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let block_commitment_cache = Arc::new(RwLock::new(
             BlockCommitmentCache::new_for_tests_with_slots(slot, slot),
         ));

+ 1 - 1
rpc/src/optimistically_confirmed_bank_tracker.rs

@@ -424,7 +424,7 @@ mod tests {
         let exit = Arc::new(AtomicBool::new(false));
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
         bank_forks.write().unwrap().insert(bank1);

+ 3 - 6
rpc/src/rpc.rs

@@ -346,10 +346,7 @@ impl JsonRpcRequestProcessor {
         connection_cache: Arc<ConnectionCache>,
     ) -> Self {
         let genesis_hash = bank.hash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new_from_banks(
-            &[bank.clone()],
-            bank.slot(),
-        )));
+        let bank_forks = BankForks::new_from_banks(&[bank.clone()], bank.slot());
         let blockstore = Arc::new(Blockstore::open(&get_tmp_ledger_path!()).unwrap());
         let exit = Arc::new(AtomicBool::new(false));
         let cluster_info = Arc::new({
@@ -6627,7 +6624,7 @@ pub mod tests {
 
         let bank = Bank::new_for_tests_with_config(&genesis_config, config);
         (
-            Arc::new(RwLock::new(BankForks::new(bank))),
+            BankForks::new_rw_arc(bank),
             mint_keypair,
             Arc::new(voting_keypair),
         )
@@ -8310,7 +8307,7 @@ pub mod tests {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100);
         let bank = Bank::new_for_tests(&genesis_config);
 
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
         bank_forks.write().unwrap().insert(bank1);

+ 1 - 1
rpc/src/rpc_health.rs

@@ -150,7 +150,7 @@ pub mod tests {
         let blockstore = Arc::new(Blockstore::open(ledger_path.path()).unwrap());
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
         let bank0 = bank_forks.read().unwrap().root_bank();

+ 12 - 14
rpc/src/rpc_pubsub.rs

@@ -684,7 +684,7 @@ mod tests {
         let bob_pubkey = bob.pubkey();
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
         let rpc_subscriptions = Arc::new(RpcSubscriptions::new_for_tests(
@@ -813,7 +813,7 @@ mod tests {
         let bob_pubkey = solana_sdk::pubkey::new_rand();
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let mut io = IoHandler::<()>::default();
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
@@ -871,7 +871,7 @@ mod tests {
         let stake_program_id = stake::program::id();
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
         bank_forks.write().unwrap().insert(bank1);
@@ -999,7 +999,7 @@ mod tests {
         let nonce_account = Keypair::new();
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
         bank_forks.write().unwrap().insert(bank1);
@@ -1088,9 +1088,7 @@ mod tests {
         let bob_pubkey = solana_sdk::pubkey::new_rand();
 
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(Bank::new_for_tests(
-            &genesis_config,
-        ))));
+        let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
 
         let mut io = IoHandler::<()>::default();
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
@@ -1138,7 +1136,7 @@ mod tests {
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bob = Keypair::new();
 
         let exit = Arc::new(AtomicBool::new(false));
@@ -1190,7 +1188,7 @@ mod tests {
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
         bank_forks.write().unwrap().insert(bank1);
@@ -1272,7 +1270,7 @@ mod tests {
     fn test_slot_subscribe() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
         let rpc_subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks(
@@ -1305,7 +1303,7 @@ mod tests {
     fn test_slot_unsubscribe() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
         let rpc_subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks(
@@ -1348,7 +1346,7 @@ mod tests {
         );
         let exit = Arc::new(AtomicBool::new(false));
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         // Setup Subscriptions
         let optimistically_confirmed_bank =
@@ -1390,7 +1388,7 @@ mod tests {
     fn test_vote_unsubscribe() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
         let rpc_subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks(
@@ -1409,7 +1407,7 @@ mod tests {
     fn test_get_version() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
         let rpc_subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks(

+ 1 - 1
rpc/src/rpc_pubsub_service.rs

@@ -485,7 +485,7 @@ mod tests {
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
         let subscriptions = Arc::new(RpcSubscriptions::new_for_tests(

+ 2 - 2
rpc/src/rpc_service.rs

@@ -617,7 +617,7 @@ mod tests {
             ip_addr,
             solana_net_utils::find_available_port_in_range(ip_addr, (10000, 65535)).unwrap(),
         );
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let ledger_path = get_tmp_ledger_path!();
         let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
         let block_commitment_cache = Arc::new(RwLock::new(BlockCommitmentCache::default()));
@@ -674,7 +674,7 @@ mod tests {
         } = create_genesis_config(10_000);
         genesis_config.cluster_type = ClusterType::MainnetBeta;
         let bank = Bank::new_for_tests(&genesis_config);
-        Arc::new(RwLock::new(BankForks::new(bank)))
+        BankForks::new_rw_arc(bank)
     }
 
     #[test]

+ 2 - 2
rpc/src/rpc_subscription_tracker.rs

@@ -700,7 +700,7 @@ mod tests {
     fn subscription_info() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let mut tracker = SubscriptionsTracker::new(bank_forks);
 
         tracker.subscribe(SubscriptionParams::Slot, 0.into(), || 0);
@@ -746,7 +746,7 @@ mod tests {
 
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let mut tracker = SubscriptionsTracker::new(bank_forks);
 
         tracker.subscribe(SubscriptionParams::Slot, 0.into(), || 0);

+ 20 - 18
rpc/src/rpc_subscriptions.rs

@@ -1324,7 +1324,7 @@ pub(crate) mod tests {
         } = create_genesis_config(100);
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
         bank_forks.write().unwrap().insert(bank1);
@@ -1470,7 +1470,7 @@ pub(crate) mod tests {
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
         let ledger_path = get_tmp_ledger_path!();
@@ -1590,7 +1590,7 @@ pub(crate) mod tests {
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
         let ledger_path = get_tmp_ledger_path!();
@@ -1708,7 +1708,7 @@ pub(crate) mod tests {
         } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         let rent_exempt_amount = bank.get_minimum_balance_for_rent_exemption(0);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
         let ledger_path = get_tmp_ledger_path!();
@@ -1826,7 +1826,7 @@ pub(crate) mod tests {
         } = create_genesis_config(100);
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let alice = Keypair::new();
         let tx = system_transaction::create_account(
             &mint_keypair,
@@ -1938,7 +1938,7 @@ pub(crate) mod tests {
         bank.lazy_rent_collection.store(true, Relaxed);
 
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
@@ -2133,7 +2133,7 @@ pub(crate) mod tests {
         bank.lazy_rent_collection.store(true, Relaxed);
 
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
@@ -2249,7 +2249,7 @@ pub(crate) mod tests {
         bank.lazy_rent_collection.store(true, Relaxed);
 
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
@@ -2435,7 +2435,8 @@ pub(crate) mod tests {
         } = create_genesis_config(100);
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks_arc = BankForks::new_rw_arc(bank);
+        let mut bank_forks = bank_forks_arc.write().unwrap();
         let alice = Keypair::new();
 
         let past_bank_tx =
@@ -2465,8 +2466,6 @@ pub(crate) mod tests {
             .unwrap();
         let bank1 = bank_forks[1].clone();
 
-        let bank_forks = Arc::new(RwLock::new(bank_forks));
-
         let mut cache0 = BlockCommitment::default();
         cache0.increase_confirmation_stake(1, 10);
         let cache1 = BlockCommitment::default();
@@ -2483,16 +2482,19 @@ pub(crate) mod tests {
             },
         );
 
+        // Drop the write locked bank_forks
+        drop(bank_forks);
+
         let exit = Arc::new(AtomicBool::new(false));
         let optimistically_confirmed_bank =
-            OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
+            OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks_arc);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
         let subscriptions = Arc::new(RpcSubscriptions::new_for_tests(
             exit,
             max_complete_transaction_status_slot,
             max_complete_rewards_slot,
-            bank_forks,
+            bank_forks_arc,
             Arc::new(RwLock::new(block_commitment_cache)),
             optimistically_confirmed_bank,
         ));
@@ -2659,7 +2661,7 @@ pub(crate) mod tests {
         let exit = Arc::new(AtomicBool::new(false));
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
@@ -2706,7 +2708,7 @@ pub(crate) mod tests {
         let exit = Arc::new(AtomicBool::new(false));
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let optimistically_confirmed_bank =
             OptimisticallyConfirmedBank::locked_from_bank_forks_root(&bank_forks);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
@@ -2755,7 +2757,7 @@ pub(crate) mod tests {
         } = create_genesis_config(100);
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank0 = bank_forks.read().unwrap().get(0).unwrap();
         let bank1 = Bank::new_from_parent(bank0.clone(), &Pubkey::default(), 1);
         bank_forks.write().unwrap().insert(bank1);
@@ -2969,7 +2971,7 @@ pub(crate) mod tests {
         } = create_genesis_config(100);
         let bank = Bank::new_for_tests(&genesis_config);
         let blockhash = bank.last_blockhash();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let alice = Keypair::new();
 
@@ -3053,7 +3055,7 @@ pub(crate) mod tests {
         let bank = Bank::new_for_tests(&genesis_config);
         let max_complete_transaction_status_slot = Arc::new(AtomicU64::default());
         let max_complete_rewards_slot = Arc::new(AtomicU64::default());
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let subscriptions = Arc::new(RpcSubscriptions::default_with_bank_forks(
             max_complete_transaction_status_slot,
             max_complete_rewards_slot,

+ 2 - 2
runtime/benches/prioritization_fee_cache.rs

@@ -100,8 +100,8 @@ fn bench_process_transactions_multiple_slots(bencher: &mut Bencher) {
 
     let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
     let bank0 = Bank::new_for_benches(&genesis_config);
-    let bank_forks = BankForks::new(bank0);
-    let bank = bank_forks.working_bank();
+    let bank_forks = BankForks::new_rw_arc(bank0);
+    let bank = bank_forks.read().unwrap().working_bank();
     let collector = solana_sdk::pubkey::new_rand();
     let banks = (1..=NUM_SLOTS)
         .map(|n| Arc::new(Bank::new_from_parent(bank.clone(), &collector, n as u64)))

+ 12 - 5
runtime/src/bank/tests.rs

@@ -12505,8 +12505,8 @@ fn test_runtime_feature_enable_with_program_cache() {
     genesis_config
         .accounts
         .remove(&feature_set::reject_callx_r10::id());
-    let mut bank_forks = BankForks::new(Bank::new_for_tests(&genesis_config));
-    let root_bank = bank_forks.root_bank();
+    let bank_forks = BankForks::new_rw_arc(Bank::new_for_tests(&genesis_config));
+    let root_bank = bank_forks.read().unwrap().root_bank();
 
     // Test a basic transfer
     let amount = genesis_config.rent.minimum_balance(0);
@@ -12565,9 +12565,16 @@ fn test_runtime_feature_enable_with_program_cache() {
 
     // Reroot to call LoadedPrograms::prune() and end the current recompilation phase
     goto_end_of_slot(&bank);
-    bank_forks.insert(Arc::into_inner(bank).unwrap());
-    let bank = bank_forks.working_bank();
-    bank_forks.set_root(bank.slot, &AbsRequestSender::default(), None);
+    bank_forks
+        .write()
+        .unwrap()
+        .insert(Arc::into_inner(bank).unwrap());
+    let bank = bank_forks.read().unwrap().working_bank();
+    bank_forks.read().unwrap().prune_program_cache(bank.slot);
+    bank_forks
+        .write()
+        .unwrap()
+        .set_root(bank.slot, &AbsRequestSender::default(), None);
 
     // Advance to next epoch, which starts the next recompilation phase
     let bank = new_from_parent_next_epoch(bank, 1);

+ 63 - 43
runtime/src/bank_forks.rs

@@ -15,7 +15,7 @@ use {
         ops::Index,
         sync::{
             atomic::{AtomicBool, AtomicU64, Ordering},
-            Arc,
+            Arc, RwLock,
         },
         time::Instant,
     },
@@ -77,7 +77,7 @@ impl Index<u64> for BankForks {
 }
 
 impl BankForks {
-    pub fn new(bank: Bank) -> Self {
+    pub fn new_rw_arc(bank: Bank) -> Arc<RwLock<Self>> {
         let root = bank.slot();
         Self::new_from_banks(&[Arc::new(bank)], root)
     }
@@ -154,7 +154,7 @@ impl BankForks {
         self[self.root()].clone()
     }
 
-    pub fn new_from_banks(initial_forks: &[Arc<Bank>], root: Slot) -> Self {
+    pub fn new_from_banks(initial_forks: &[Arc<Bank>], root: Slot) -> Arc<RwLock<Self>> {
         let mut banks = HashMap::new();
 
         // Iterate through the heads of all the different forks
@@ -175,7 +175,7 @@ impl BankForks {
                 descendants.entry(parent).or_default().insert(*slot);
             }
         }
-        Self {
+        let bank_forks = Arc::new(RwLock::new(Self {
             root: Arc::new(AtomicSlot::new(root)),
             banks,
             descendants,
@@ -184,7 +184,16 @@ impl BankForks {
             last_accounts_hash_slot: root,
             in_vote_only_mode: Arc::new(AtomicBool::new(false)),
             highest_slot_at_startup: 0,
+        }));
+
+        for bank in bank_forks.read().unwrap().banks.values() {
+            bank.loaded_programs_cache
+                .write()
+                .unwrap()
+                .set_fork_graph(bank_forks.clone());
         }
+
+        bank_forks
     }
 
     pub fn insert(&mut self, mut bank: Bank) -> Arc<Bank> {
@@ -696,7 +705,8 @@ mod tests {
     fn test_bank_forks_new() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks = BankForks::new_rw_arc(bank);
+        let mut bank_forks = bank_forks.write().unwrap();
         let child_bank = Bank::new_from_parent(bank_forks[0].clone(), &Pubkey::default(), 1);
         child_bank.register_tick(&Hash::default());
         bank_forks.insert(child_bank);
@@ -711,19 +721,20 @@ mod tests {
         let child_bank = Arc::new(Bank::new_from_parent(bank.clone(), &Pubkey::default(), 1));
 
         let bank_forks = BankForks::new_from_banks(&[bank.clone(), child_bank.clone()], 0);
-        assert_eq!(bank_forks.root(), 0);
-        assert_eq!(bank_forks.working_bank().slot(), 1);
+        assert_eq!(bank_forks.read().unwrap().root(), 0);
+        assert_eq!(bank_forks.read().unwrap().working_bank().slot(), 1);
 
         let bank_forks = BankForks::new_from_banks(&[child_bank, bank], 0);
-        assert_eq!(bank_forks.root(), 0);
-        assert_eq!(bank_forks.working_bank().slot(), 1);
+        assert_eq!(bank_forks.read().unwrap().root(), 0);
+        assert_eq!(bank_forks.read().unwrap().working_bank().slot(), 1);
     }
 
     #[test]
     fn test_bank_forks_descendants() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks = BankForks::new_rw_arc(bank);
+        let mut bank_forks = bank_forks.write().unwrap();
         let bank0 = bank_forks[0].clone();
         let bank = Bank::new_from_parent(bank0.clone(), &Pubkey::default(), 1);
         bank_forks.insert(bank);
@@ -740,7 +751,8 @@ mod tests {
     fn test_bank_forks_ancestors() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks = BankForks::new_rw_arc(bank);
+        let mut bank_forks = bank_forks.write().unwrap();
         let bank0 = bank_forks[0].clone();
         let bank = Bank::new_from_parent(bank0.clone(), &Pubkey::default(), 1);
         bank_forks.insert(bank);
@@ -758,7 +770,8 @@ mod tests {
     fn test_bank_forks_frozen_banks() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks = BankForks::new_rw_arc(bank);
+        let mut bank_forks = bank_forks.write().unwrap();
         let bank0 = bank_forks[0].clone();
         let child_bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
         bank_forks.insert(child_bank);
@@ -770,7 +783,8 @@ mod tests {
     fn test_bank_forks_active_banks() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks = BankForks::new_rw_arc(bank);
+        let mut bank_forks = bank_forks.write().unwrap();
         let bank0 = bank_forks[0].clone();
         let child_bank = Bank::new_from_parent(bank0, &Pubkey::default(), 1);
         bank_forks.insert(child_bank);
@@ -822,11 +836,13 @@ mod tests {
         };
 
         let bank0 = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks0 = BankForks::new(bank0);
+        let bank_forks0 = BankForks::new_rw_arc(bank0);
+        let mut bank_forks0 = bank_forks0.write().unwrap();
         bank_forks0.set_root(0, &abs_request_sender, None);
 
         let bank1 = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks1 = BankForks::new(bank1);
+        let bank_forks1 = BankForks::new_rw_arc(bank1);
+        let mut bank_forks1 = bank_forks1.write().unwrap();
 
         let additional_timestamp_secs = 2;
 
@@ -882,10 +898,11 @@ mod tests {
             .collect()
     }
 
-    fn extend_bank_forks(bank_forks: &mut BankForks, parent_child_pairs: &[(Slot, Slot)]) {
+    fn extend_bank_forks(bank_forks: Arc<RwLock<BankForks>>, parent_child_pairs: &[(Slot, Slot)]) {
         for (parent, child) in parent_child_pairs.iter() {
-            bank_forks.insert(Bank::new_from_parent(
-                bank_forks[*parent].clone(),
+            let parent: Arc<Bank> = bank_forks.read().unwrap().banks[parent].clone();
+            bank_forks.write().unwrap().insert(Bank::new_from_parent(
+                parent,
                 &Pubkey::default(),
                 *child,
             ));
@@ -896,13 +913,13 @@ mod tests {
     fn test_bank_forks_with_set_root() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let parent_child_pairs = vec![(0, 1), (1, 2), (0, 3), (3, 4)];
-        extend_bank_forks(&mut bank_forks, &parent_child_pairs);
+        extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
 
         assert_eq!(
-            bank_forks.ancestors(),
+            bank_forks.read().unwrap().ancestors(),
             make_hash_map(vec![
                 (0, vec![]),
                 (1, vec![0]),
@@ -912,7 +929,7 @@ mod tests {
             ])
         );
         assert_eq!(
-            bank_forks.descendants(),
+            bank_forks.read().unwrap().descendants(),
             make_hash_map(vec![
                 (0, vec![1, 2, 3, 4]),
                 (1, vec![2]),
@@ -921,26 +938,29 @@ mod tests {
                 (4, vec![]),
             ])
         );
-        bank_forks.set_root(
+        bank_forks.write().unwrap().set_root(
             2,
             &AbsRequestSender::default(),
             None, // highest confirmed root
         );
-        bank_forks[2].squash();
-        assert_eq!(bank_forks.ancestors(), make_hash_map(vec![(2, vec![]),]));
+        bank_forks.read().unwrap().get(2).unwrap().squash();
         assert_eq!(
-            bank_forks.descendants(),
+            bank_forks.read().unwrap().ancestors(),
+            make_hash_map(vec![(2, vec![]),])
+        );
+        assert_eq!(
+            bank_forks.read().unwrap().descendants(),
             make_hash_map(vec![(0, vec![2]), (1, vec![2]), (2, vec![]),])
         );
 
         let parent_child_pairs = vec![(2, 5), (5, 6)];
-        extend_bank_forks(&mut bank_forks, &parent_child_pairs);
+        extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
         assert_eq!(
-            bank_forks.ancestors(),
+            bank_forks.read().unwrap().ancestors(),
             make_hash_map(vec![(2, vec![]), (5, vec![2]), (6, vec![2, 5])])
         );
         assert_eq!(
-            bank_forks.descendants(),
+            bank_forks.read().unwrap().descendants(),
             make_hash_map(vec![
                 (0, vec![2]),
                 (1, vec![2]),
@@ -956,13 +976,13 @@ mod tests {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
         assert_eq!(bank.slot(), 0);
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let parent_child_pairs = vec![(0, 1), (1, 2), (0, 3), (3, 4)];
-        extend_bank_forks(&mut bank_forks, &parent_child_pairs);
+        extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
 
         assert_eq!(
-            bank_forks.ancestors(),
+            bank_forks.read().unwrap().ancestors(),
             make_hash_map(vec![
                 (0, vec![]),
                 (1, vec![0]),
@@ -972,7 +992,7 @@ mod tests {
             ])
         );
         assert_eq!(
-            bank_forks.descendants(),
+            bank_forks.read().unwrap().descendants(),
             make_hash_map(vec![
                 (0, vec![1, 2, 3, 4]),
                 (1, vec![2]),
@@ -981,25 +1001,25 @@ mod tests {
                 (4, vec![]),
             ])
         );
-        bank_forks.set_root(
+        bank_forks.write().unwrap().set_root(
             2,
             &AbsRequestSender::default(),
             Some(1), // highest confirmed root
         );
-        bank_forks[2].squash();
+        bank_forks.read().unwrap().get(2).unwrap().squash();
         assert_eq!(
-            bank_forks.ancestors(),
+            bank_forks.read().unwrap().ancestors(),
             make_hash_map(vec![(1, vec![]), (2, vec![]),])
         );
         assert_eq!(
-            bank_forks.descendants(),
+            bank_forks.read().unwrap().descendants(),
             make_hash_map(vec![(0, vec![1, 2]), (1, vec![2]), (2, vec![]),])
         );
 
         let parent_child_pairs = vec![(2, 5), (5, 6)];
-        extend_bank_forks(&mut bank_forks, &parent_child_pairs);
+        extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
         assert_eq!(
-            bank_forks.ancestors(),
+            bank_forks.read().unwrap().ancestors(),
             make_hash_map(vec![
                 (1, vec![]),
                 (2, vec![]),
@@ -1008,7 +1028,7 @@ mod tests {
             ])
         );
         assert_eq!(
-            bank_forks.descendants(),
+            bank_forks.read().unwrap().descendants(),
             make_hash_map(vec![
                 (0, vec![1, 2]),
                 (1, vec![2]),
@@ -1023,7 +1043,7 @@ mod tests {
     fn test_fork_graph() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let mut bank_forks = BankForks::new(bank);
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let parent_child_pairs = vec![
             (0, 1),
@@ -1036,7 +1056,7 @@ mod tests {
             (4, 6),
             (6, 12),
         ];
-        extend_bank_forks(&mut bank_forks, &parent_child_pairs);
+        extend_bank_forks(bank_forks.clone(), &parent_child_pairs);
 
         // Fork graph created for the test
         //                   0
@@ -1048,7 +1068,7 @@ mod tests {
         //                8     5  6
         //                      |   |
         //                      10  12
-
+        let mut bank_forks = bank_forks.write().unwrap();
         assert_matches!(bank_forks.relationship(0, 3), BlockRelation::Ancestor);
         assert_matches!(bank_forks.relationship(0, 10), BlockRelation::Ancestor);
         assert_matches!(bank_forks.relationship(0, 12), BlockRelation::Ancestor);

+ 4 - 4
runtime/src/prioritization_fee_cache.rs

@@ -612,8 +612,8 @@ mod tests {
 
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank0 = Bank::new_for_benches(&genesis_config);
-        let bank_forks = BankForks::new(bank0);
-        let bank = bank_forks.working_bank();
+        let bank_forks = BankForks::new_rw_arc(bank0);
+        let bank = bank_forks.read().unwrap().working_bank();
         let collector = solana_sdk::pubkey::new_rand();
         let bank1 = Arc::new(Bank::new_from_parent(bank.clone(), &collector, 1));
         let bank2 = Arc::new(Bank::new_from_parent(bank.clone(), &collector, 2));
@@ -864,8 +864,8 @@ mod tests {
 
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank0 = Bank::new_for_benches(&genesis_config);
-        let bank_forks = BankForks::new(bank0);
-        let bank = bank_forks.working_bank();
+        let bank_forks = BankForks::new_rw_arc(bank0);
+        let bank = bank_forks.read().unwrap().working_bank();
         let collector = solana_sdk::pubkey::new_rand();
         let slot: Slot = 999;
         let bank1 = Arc::new(Bank::new_from_parent(bank.clone(), &collector, slot));

+ 1 - 1
runtime/src/root_bank_cache.rs

@@ -60,7 +60,7 @@ mod tests {
     fn test_root_bank_cache() {
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
 
         let mut root_bank_cache = RootBankCache::new(bank_forks.clone());
 

+ 4 - 4
send-transaction-service/src/send_transaction_service.rs

@@ -826,7 +826,7 @@ mod test {
     fn service_exit() {
         let tpu_address = "127.0.0.1:0".parse().unwrap();
         let bank = Bank::default_for_tests();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let (sender, receiver) = unbounded();
 
         let connection_cache = Arc::new(ConnectionCache::new("connection_cache_test"));
@@ -849,7 +849,7 @@ mod test {
     fn validator_exit() {
         let tpu_address = "127.0.0.1:0".parse().unwrap();
         let bank = Bank::default_for_tests();
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let (sender, receiver) = bounded(0);
 
         let dummy_tx_info = || TransactionInfo {
@@ -893,7 +893,7 @@ mod test {
 
         let (genesis_config, mint_keypair) = create_genesis_config(4);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let tpu_address = "127.0.0.1:0".parse().unwrap();
         let config = Config {
             leader_forward_count: 1,
@@ -1159,7 +1159,7 @@ mod test {
 
         let (genesis_config, mint_keypair) = create_genesis_config(4);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let tpu_address = "127.0.0.1:0".parse().unwrap();
         let config = Config {
             leader_forward_count: 1,

+ 2 - 7
turbine/benches/cluster_info.rs

@@ -25,12 +25,7 @@ use {
         },
         cluster_nodes::ClusterNodesCache,
     },
-    std::{
-        collections::HashMap,
-        net::UdpSocket,
-        sync::{Arc, RwLock},
-        time::Duration,
-    },
+    std::{collections::HashMap, net::UdpSocket, sync::Arc, time::Duration},
     test::Bencher,
 };
 
@@ -49,7 +44,7 @@ fn broadcast_shreds_bench(bencher: &mut Bencher) {
     let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
     let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
     let bank = Bank::new_for_benches(&genesis_config);
-    let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+    let bank_forks = BankForks::new_rw_arc(bank);
 
     const NUM_SHREDS: usize = 32;
     let shred = Shred::new_from_data(0, 0, 0, &[], ShredFlags::empty(), 0, 0, 0);

+ 3 - 4
turbine/benches/retransmit_stage.rs

@@ -32,7 +32,7 @@ use {
         net::{Ipv4Addr, UdpSocket},
         sync::{
             atomic::{AtomicUsize, Ordering},
-            Arc, RwLock,
+            Arc,
         },
         thread::{sleep, Builder},
         time::Duration,
@@ -74,9 +74,8 @@ fn bench_retransmitter(bencher: &mut Bencher) {
 
     let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(100_000);
     let bank0 = Bank::new_for_benches(&genesis_config);
-    let bank_forks = BankForks::new(bank0);
-    let bank = bank_forks.working_bank();
-    let bank_forks = Arc::new(RwLock::new(bank_forks));
+    let bank_forks = BankForks::new_rw_arc(bank0);
+    let bank = bank_forks.read().unwrap().working_bank();
     let (shreds_sender, shreds_receiver) = unbounded();
     const NUM_THREADS: usize = 2;
     let sockets = (0..NUM_THREADS)

+ 1 - 1
turbine/src/broadcast_stage.rs

@@ -668,7 +668,7 @@ pub mod test {
 
         let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank = bank_forks.read().unwrap().root_bank();
 
         // Start up the broadcast stage

+ 1 - 1
turbine/src/broadcast_stage/standard_broadcast_run.rs

@@ -544,7 +544,7 @@ mod test {
         genesis_config.ticks_per_slot = max_ticks_per_n_shreds(num_shreds_per_slot, None) + 1;
 
         let bank = Bank::new_for_tests(&genesis_config);
-        let bank_forks = Arc::new(RwLock::new(BankForks::new(bank)));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let bank0 = bank_forks.read().unwrap().root_bank();
         (
             blockstore,

+ 1 - 1
turbine/src/quic_endpoint.rs

@@ -598,7 +598,7 @@ mod tests {
             let GenesisConfigInfo { genesis_config, .. } =
                 create_genesis_config(/*mint_lamports:*/ 100_000);
             let bank = Bank::new_for_tests(&genesis_config);
-            Arc::new(RwLock::new(BankForks::new(bank)))
+            BankForks::new_rw_arc(bank)
         };
         let (endpoints, senders, tasks): (Vec<_>, Vec<_>, Vec<_>) =
             multiunzip(keypairs.iter().zip(sockets).zip(senders).map(

+ 1 - 1
turbine/src/sigverify_shreds.rs

@@ -284,7 +284,7 @@ mod tests {
             &create_genesis_config_with_leader(100, &leader_pubkey, 10).genesis_config,
         );
         let leader_schedule_cache = LeaderScheduleCache::new_from_bank(&bank);
-        let bank_forks = RwLock::new(BankForks::new(bank));
+        let bank_forks = BankForks::new_rw_arc(bank);
         let batch_size = 2;
         let mut batch = PacketBatch::with_capacity(batch_size);
         batch.resize(batch_size, Packet::default());

+ 1 - 4
validator/src/admin_rpc_service.rs

@@ -917,10 +917,7 @@ mod tests {
         } = create_genesis_config(1_000_000_000);
 
         let bank = Bank::new_for_tests_with_config(&genesis_config, config);
-        (
-            Arc::new(RwLock::new(BankForks::new(bank))),
-            Arc::new(voting_keypair),
-        )
+        (BankForks::new_rw_arc(bank), Arc::new(voting_keypair))
     }
 
     #[test]

Някои файлове не бяха показани, защото твърде много файлове са промени