99 itertools:: Itertools ,
1010 solana_compute_budget:: compute_budget_limits:: ComputeBudgetLimits ,
1111 solana_feature_set:: { self as feature_set, FeatureSet } ,
12- solana_program_runtime:: loaded_programs:: { ProgramCacheEntry , ProgramCacheForTxBatch } ,
12+ solana_program_runtime:: loaded_programs:: ProgramCacheForTxBatch ,
1313 solana_sdk:: {
1414 account:: { Account , AccountSharedData , ReadableAccount , WritableAccount } ,
1515 fee:: FeeDetails ,
3030 solana_svm_rent_collector:: svm_rent_collector:: SVMRentCollector ,
3131 solana_svm_transaction:: svm_message:: SVMMessage ,
3232 solana_system_program:: { get_system_account_kind, SystemAccountKind } ,
33- std:: num:: NonZeroU32 ,
33+ std:: { collections :: HashMap , num:: NonZeroU32 } ,
3434} ;
3535
3636// for the load instructions
@@ -194,6 +194,7 @@ pub(crate) fn load_accounts<CB: TransactionProcessingCallback>(
194194 account_overrides : Option < & AccountOverrides > ,
195195 feature_set : & FeatureSet ,
196196 rent_collector : & dyn SVMRentCollector ,
197+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
197198 loaded_programs : & ProgramCacheForTxBatch ,
198199) -> Vec < TransactionLoadResult > {
199200 txs. iter ( )
@@ -207,6 +208,7 @@ pub(crate) fn load_accounts<CB: TransactionProcessingCallback>(
207208 account_overrides,
208209 feature_set,
209210 rent_collector,
211+ program_accounts,
210212 loaded_programs,
211213 )
212214 } )
@@ -221,6 +223,7 @@ fn load_transaction<CB: TransactionProcessingCallback>(
221223 account_overrides : Option < & AccountOverrides > ,
222224 feature_set : & FeatureSet ,
223225 rent_collector : & dyn SVMRentCollector ,
226+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
224227 loaded_programs : & ProgramCacheForTxBatch ,
225228) -> TransactionLoadResult {
226229 match validation_result {
@@ -235,6 +238,7 @@ fn load_transaction<CB: TransactionProcessingCallback>(
235238 account_overrides,
236239 feature_set,
237240 rent_collector,
241+ program_accounts,
238242 loaded_programs,
239243 ) ;
240244
@@ -268,6 +272,7 @@ struct LoadedTransactionAccounts {
268272 pub loaded_accounts_data_size : u32 ,
269273}
270274
275+ #[ allow( clippy:: too_many_arguments) ]
271276fn load_transaction_accounts < CB : TransactionProcessingCallback > (
272277 callbacks : & CB ,
273278 message : & impl SVMMessage ,
@@ -277,6 +282,7 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
277282 account_overrides : Option < & AccountOverrides > ,
278283 feature_set : & FeatureSet ,
279284 rent_collector : & dyn SVMRentCollector ,
285+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
280286 loaded_programs : & ProgramCacheForTxBatch ,
281287) -> Result < LoadedTransactionAccounts > {
282288 let mut tx_rent: TransactionRent = 0 ;
@@ -331,6 +337,7 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
331337 account_overrides,
332338 feature_set,
333339 rent_collector,
340+ program_accounts,
334341 loaded_programs,
335342 ) ?;
336343 collect_loaded_account ( account_key, ( loaded_account, account_found) ) ?;
@@ -403,6 +410,7 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
403410 } )
404411}
405412
413+ #[ allow( clippy:: too_many_arguments) ]
406414fn load_transaction_account < CB : TransactionProcessingCallback > (
407415 callbacks : & CB ,
408416 message : & impl SVMMessage ,
@@ -412,6 +420,7 @@ fn load_transaction_account<CB: TransactionProcessingCallback>(
412420 account_overrides : Option < & AccountOverrides > ,
413421 feature_set : & FeatureSet ,
414422 rent_collector : & dyn SVMRentCollector ,
423+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
415424 loaded_programs : & ProgramCacheForTxBatch ,
416425) -> Result < ( LoadedTransactionAccount , bool ) > {
417426 let mut account_found = true ;
@@ -439,14 +448,11 @@ fn load_transaction_account<CB: TransactionProcessingCallback>(
439448 . then_some ( ( ) )
440449 . and_then ( |_| loaded_programs. find ( account_key) )
441450 {
442- callbacks
443- . get_account_shared_data ( account_key)
444- . ok_or ( TransactionError :: AccountNotFound ) ?;
445451 // Optimization to skip loading of accounts which are only used as
446452 // programs in top-level instructions and not passed as instruction accounts.
447453 LoadedTransactionAccount {
448454 loaded_size : program. account_size ,
449- account : account_shared_data_from_program ( & program ) ,
455+ account : account_shared_data_from_program ( account_key , program_accounts ) ? ,
450456 rent_collected : 0 ,
451457 }
452458 } else {
@@ -496,14 +502,20 @@ fn load_transaction_account<CB: TransactionProcessingCallback>(
496502 Ok ( ( loaded_account, account_found) )
497503}
498504
499- fn account_shared_data_from_program ( loaded_program : & ProgramCacheEntry ) -> AccountSharedData {
505+ fn account_shared_data_from_program (
506+ key : & Pubkey ,
507+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
508+ ) -> Result < AccountSharedData > {
500509 // It's an executable program account. The program is already loaded in the cache.
501510 // So the account data is not needed. Return a dummy AccountSharedData with meta
502511 // information.
503512 let mut program_account = AccountSharedData :: default ( ) ;
504- program_account. set_owner ( loaded_program. account_owner ( ) ) ;
513+ let ( program_owner, _count) = program_accounts
514+ . get ( key)
515+ . ok_or ( TransactionError :: AccountNotFound ) ?;
516+ program_account. set_owner ( * * program_owner) ;
505517 program_account. set_executable ( true ) ;
506- program_account
518+ Ok ( program_account)
507519}
508520
509521/// Accumulate loaded account data size into `accumulated_accounts_data_size`.
@@ -670,6 +682,7 @@ mod tests {
670682 None ,
671683 feature_set,
672684 rent_collector,
685+ & HashMap :: new ( ) ,
673686 & ProgramCacheForTxBatch :: default ( ) ,
674687 )
675688 }
@@ -978,6 +991,7 @@ mod tests {
978991 account_overrides,
979992 & FeatureSet :: all_enabled ( ) ,
980993 & RentCollector :: default ( ) ,
994+ & HashMap :: new ( ) ,
981995 & ProgramCacheForTxBatch :: default ( ) ,
982996 )
983997 }
@@ -1273,6 +1287,7 @@ mod tests {
12731287 None ,
12741288 & FeatureSet :: default ( ) ,
12751289 & RentCollector :: default ( ) ,
1290+ & HashMap :: new ( ) ,
12761291 & loaded_programs,
12771292 ) ;
12781293
@@ -1338,6 +1353,7 @@ mod tests {
13381353 None ,
13391354 & FeatureSet :: default ( ) ,
13401355 & RentCollector :: default ( ) ,
1356+ & HashMap :: new ( ) ,
13411357 & loaded_programs,
13421358 ) ;
13431359
@@ -1371,6 +1387,7 @@ mod tests {
13711387 let mut mock_bank = TestCallbacks :: default ( ) ;
13721388 let account_keypair = Keypair :: new ( ) ;
13731389 let program_keypair = Keypair :: new ( ) ;
1390+ let loader_v2 = bpf_loader:: id ( ) ;
13741391
13751392 let mut account_data = AccountSharedData :: default ( ) ;
13761393 account_data. set_lamports ( 200 ) ;
@@ -1380,7 +1397,7 @@ mod tests {
13801397
13811398 let mut program_data = AccountSharedData :: default ( ) ;
13821399 program_data. set_lamports ( 200 ) ;
1383- program_data. set_owner ( bpf_loader :: id ( ) ) ;
1400+ program_data. set_owner ( loader_v2 ) ;
13841401 mock_bank
13851402 . accounts_map
13861403 . insert ( program_keypair. pubkey ( ) , program_data) ;
@@ -1391,7 +1408,7 @@ mod tests {
13911408 loader_data. set_owner ( native_loader:: id ( ) ) ;
13921409 mock_bank
13931410 . accounts_map
1394- . insert ( bpf_loader :: id ( ) , loader_data. clone ( ) ) ;
1411+ . insert ( loader_v2 , loader_data. clone ( ) ) ;
13951412 mock_bank
13961413 . accounts_map
13971414 . insert ( native_loader:: id ( ) , loader_data. clone ( ) ) ;
@@ -1408,6 +1425,8 @@ mod tests {
14081425 Hash :: default ( ) ,
14091426 ) ) ;
14101427
1428+ let mut program_accounts = HashMap :: new ( ) ;
1429+ program_accounts. insert ( program_keypair. pubkey ( ) , ( & loader_v2, 0 ) ) ;
14111430 let mut loaded_programs = ProgramCacheForTxBatch :: default ( ) ;
14121431 loaded_programs. replenish (
14131432 program_keypair. pubkey ( ) ,
@@ -1431,12 +1450,13 @@ mod tests {
14311450 None ,
14321451 & FeatureSet :: default ( ) ,
14331452 & RentCollector :: default ( ) ,
1453+ & program_accounts,
14341454 & loaded_programs,
14351455 ) ;
14361456
14371457 // Executable flag is bypassed
14381458 let mut cached_program = AccountSharedData :: default ( ) ;
1439- cached_program. set_owner ( bpf_loader :: id ( ) ) ;
1459+ cached_program. set_owner ( loader_v2 ) ;
14401460 cached_program. set_executable ( true ) ;
14411461
14421462 assert_eq ! (
@@ -1445,7 +1465,7 @@ mod tests {
14451465 accounts: vec![
14461466 ( account_keypair. pubkey( ) , account_data. clone( ) ) ,
14471467 ( program_keypair. pubkey( ) , cached_program) ,
1448- ( bpf_loader :: id ( ) , loader_data) ,
1468+ ( loader_v2 , loader_data) ,
14491469 ] ,
14501470 program_indices: vec![ vec![ 1 ] ] ,
14511471 rent: 0 ,
@@ -1478,6 +1498,7 @@ mod tests {
14781498 None ,
14791499 & FeatureSet :: default ( ) ,
14801500 & RentCollector :: default ( ) ,
1501+ & program_accounts,
14811502 & loaded_programs,
14821503 ) ;
14831504
@@ -1504,6 +1525,7 @@ mod tests {
15041525 None ,
15051526 & FeatureSet :: default ( ) ,
15061527 & RentCollector :: default ( ) ,
1528+ & program_accounts,
15071529 & loaded_programs,
15081530 ) ;
15091531
@@ -1553,6 +1575,7 @@ mod tests {
15531575 None ,
15541576 & FeatureSet :: default ( ) ,
15551577 & RentCollector :: default ( ) ,
1578+ & HashMap :: new ( ) ,
15561579 & loaded_programs,
15571580 ) ;
15581581
@@ -1598,6 +1621,7 @@ mod tests {
15981621 None ,
15991622 & FeatureSet :: default ( ) ,
16001623 & RentCollector :: default ( ) ,
1624+ & HashMap :: new ( ) ,
16011625 & loaded_programs,
16021626 ) ;
16031627
@@ -1655,6 +1679,7 @@ mod tests {
16551679 None ,
16561680 & FeatureSet :: default ( ) ,
16571681 & RentCollector :: default ( ) ,
1682+ & HashMap :: new ( ) ,
16581683 & loaded_programs,
16591684 ) ;
16601685
@@ -1718,6 +1743,7 @@ mod tests {
17181743 None ,
17191744 & FeatureSet :: default ( ) ,
17201745 & RentCollector :: default ( ) ,
1746+ & HashMap :: new ( ) ,
17211747 & loaded_programs,
17221748 ) ;
17231749
@@ -1772,6 +1798,7 @@ mod tests {
17721798 None ,
17731799 & FeatureSet :: default ( ) ,
17741800 & RentCollector :: default ( ) ,
1801+ & HashMap :: new ( ) ,
17751802 & loaded_programs,
17761803 ) ;
17771804
@@ -1836,6 +1863,7 @@ mod tests {
18361863 None ,
18371864 & FeatureSet :: default ( ) ,
18381865 & RentCollector :: default ( ) ,
1866+ & HashMap :: new ( ) ,
18391867 & loaded_programs,
18401868 ) ;
18411869
@@ -1924,6 +1952,7 @@ mod tests {
19241952 None ,
19251953 & FeatureSet :: default ( ) ,
19261954 & RentCollector :: default ( ) ,
1955+ & HashMap :: new ( ) ,
19271956 & loaded_programs,
19281957 ) ;
19291958
@@ -1989,6 +2018,7 @@ mod tests {
19892018 None ,
19902019 & FeatureSet :: default ( ) ,
19912020 & RentCollector :: default ( ) ,
2021+ & HashMap :: new ( ) ,
19922022 & ProgramCacheForTxBatch :: default ( ) ,
19932023 ) ;
19942024
@@ -2085,6 +2115,7 @@ mod tests {
20852115 None ,
20862116 & FeatureSet :: default ( ) ,
20872117 & RentCollector :: default ( ) ,
2118+ & HashMap :: new ( ) ,
20882119 & loaded_programs,
20892120 ) ;
20902121
@@ -2157,6 +2188,7 @@ mod tests {
21572188 None ,
21582189 & feature_set,
21592190 & rent_collector,
2191+ & HashMap :: new ( ) ,
21602192 & ProgramCacheForTxBatch :: default ( ) ,
21612193 ) ;
21622194
@@ -2178,6 +2210,7 @@ mod tests {
21782210 None ,
21792211 & feature_set,
21802212 & rent_collector,
2213+ & HashMap :: new ( ) ,
21812214 & ProgramCacheForTxBatch :: default ( ) ,
21822215 ) ;
21832216
@@ -2328,6 +2361,7 @@ mod tests {
23282361 None ,
23292362 & FeatureSet :: default ( ) ,
23302363 & RentCollector :: default ( ) ,
2364+ & HashMap :: new ( ) ,
23312365 & ProgramCacheForTxBatch :: default ( ) ,
23322366 ) ;
23332367
@@ -2355,6 +2389,8 @@ mod tests {
23552389 fn test_load_transaction_accounts_data_sizes ( ) {
23562390 let mut mock_bank = TestCallbacks :: default ( ) ;
23572391
2392+ let loader_v2 = bpf_loader:: id ( ) ;
2393+ let loader_v3 = bpf_loader_upgradeable:: id ( ) ;
23582394 let program1_keypair = Keypair :: new ( ) ;
23592395 let program1 = program1_keypair. pubkey ( ) ;
23602396 let program2 = Pubkey :: new_unique ( ) ;
@@ -2363,7 +2399,7 @@ mod tests {
23632399
23642400 let program2_size = std:: mem:: size_of :: < UpgradeableLoaderState > ( ) as u32 ;
23652401 let mut program2_account = AccountSharedData :: default ( ) ;
2366- program2_account. set_owner ( bpf_loader_upgradeable :: id ( ) ) ;
2402+ program2_account. set_owner ( loader_v3 ) ;
23672403 program2_account. set_executable ( true ) ;
23682404 program2_account. set_data ( vec ! [ 0 ; program2_size as usize ] ) ;
23692405 program2_account
@@ -2373,7 +2409,7 @@ mod tests {
23732409 . unwrap ( ) ;
23742410 mock_bank. accounts_map . insert ( program2, program2_account) ;
23752411 let mut programdata2_account = AccountSharedData :: default ( ) ;
2376- programdata2_account. set_owner ( bpf_loader_upgradeable :: id ( ) ) ;
2412+ programdata2_account. set_owner ( loader_v3 ) ;
23772413 programdata2_account. set_data ( vec ! [ 0 ; program2_size as usize ] ) ;
23782414 programdata2_account
23792415 . set_state ( & UpgradeableLoaderState :: ProgramData {
@@ -2423,12 +2459,14 @@ mod tests {
24232459 let ( account2_size, _) = make_account ( account2, program2, false ) ;
24242460
24252461 let ( native_loader_size, _) = make_account ( native_loader:: id ( ) , native_loader:: id ( ) , true ) ;
2426- let ( bpf_loader_size, _) = make_account ( bpf_loader:: id ( ) , native_loader:: id ( ) , true ) ;
2427- let ( upgradeable_loader_size, _) =
2428- make_account ( bpf_loader_upgradeable:: id ( ) , native_loader:: id ( ) , true ) ;
2462+ let ( bpf_loader_size, _) = make_account ( loader_v2, native_loader:: id ( ) , true ) ;
2463+ let ( upgradeable_loader_size, _) = make_account ( loader_v3, native_loader:: id ( ) , true ) ;
24292464
2430- let ( _program1_size, _) = make_account ( program1, bpf_loader :: id ( ) , true ) ;
2465+ let ( _program1_size, _) = make_account ( program1, loader_v2 , true ) ;
24312466
2467+ let mut program_accounts = HashMap :: new ( ) ;
2468+ program_accounts. insert ( program1, ( & loader_v2, 0 ) ) ;
2469+ program_accounts. insert ( program2, ( & loader_v3, 0 ) ) ;
24322470 let mut program_cache = ProgramCacheForTxBatch :: default ( ) ;
24332471 let program1_entry = ProgramCacheEntry {
24342472 account_size : 0 ,
@@ -2459,6 +2497,7 @@ mod tests {
24592497 None ,
24602498 & FeatureSet :: default ( ) ,
24612499 & RentCollector :: default ( ) ,
2500+ & program_accounts,
24622501 & program_cache,
24632502 )
24642503 . unwrap ( ) ;
0 commit comments