9
9
itertools:: Itertools ,
10
10
solana_compute_budget:: compute_budget_limits:: ComputeBudgetLimits ,
11
11
solana_feature_set:: { self as feature_set, FeatureSet } ,
12
- solana_program_runtime:: loaded_programs:: { ProgramCacheEntry , ProgramCacheForTxBatch } ,
12
+ solana_program_runtime:: loaded_programs:: ProgramCacheForTxBatch ,
13
13
solana_sdk:: {
14
14
account:: { Account , AccountSharedData , ReadableAccount , WritableAccount } ,
15
15
fee:: FeeDetails ,
30
30
solana_svm_rent_collector:: svm_rent_collector:: SVMRentCollector ,
31
31
solana_svm_transaction:: svm_message:: SVMMessage ,
32
32
solana_system_program:: { get_system_account_kind, SystemAccountKind } ,
33
- std:: num:: NonZeroU32 ,
33
+ std:: { collections :: HashMap , num:: NonZeroU32 } ,
34
34
} ;
35
35
36
36
// for the load instructions
@@ -194,6 +194,7 @@ pub(crate) fn load_accounts<CB: TransactionProcessingCallback>(
194
194
account_overrides : Option < & AccountOverrides > ,
195
195
feature_set : & FeatureSet ,
196
196
rent_collector : & dyn SVMRentCollector ,
197
+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
197
198
loaded_programs : & ProgramCacheForTxBatch ,
198
199
) -> Vec < TransactionLoadResult > {
199
200
txs. iter ( )
@@ -207,6 +208,7 @@ pub(crate) fn load_accounts<CB: TransactionProcessingCallback>(
207
208
account_overrides,
208
209
feature_set,
209
210
rent_collector,
211
+ program_accounts,
210
212
loaded_programs,
211
213
)
212
214
} )
@@ -221,6 +223,7 @@ fn load_transaction<CB: TransactionProcessingCallback>(
221
223
account_overrides : Option < & AccountOverrides > ,
222
224
feature_set : & FeatureSet ,
223
225
rent_collector : & dyn SVMRentCollector ,
226
+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
224
227
loaded_programs : & ProgramCacheForTxBatch ,
225
228
) -> TransactionLoadResult {
226
229
match validation_result {
@@ -235,6 +238,7 @@ fn load_transaction<CB: TransactionProcessingCallback>(
235
238
account_overrides,
236
239
feature_set,
237
240
rent_collector,
241
+ program_accounts,
238
242
loaded_programs,
239
243
) ;
240
244
@@ -268,6 +272,7 @@ struct LoadedTransactionAccounts {
268
272
pub loaded_accounts_data_size : u32 ,
269
273
}
270
274
275
+ #[ allow( clippy:: too_many_arguments) ]
271
276
fn load_transaction_accounts < CB : TransactionProcessingCallback > (
272
277
callbacks : & CB ,
273
278
message : & impl SVMMessage ,
@@ -277,6 +282,7 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
277
282
account_overrides : Option < & AccountOverrides > ,
278
283
feature_set : & FeatureSet ,
279
284
rent_collector : & dyn SVMRentCollector ,
285
+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
280
286
loaded_programs : & ProgramCacheForTxBatch ,
281
287
) -> Result < LoadedTransactionAccounts > {
282
288
let mut tx_rent: TransactionRent = 0 ;
@@ -331,6 +337,7 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
331
337
account_overrides,
332
338
feature_set,
333
339
rent_collector,
340
+ program_accounts,
334
341
loaded_programs,
335
342
) ?;
336
343
collect_loaded_account ( account_key, ( loaded_account, account_found) ) ?;
@@ -403,6 +410,7 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
403
410
} )
404
411
}
405
412
413
+ #[ allow( clippy:: too_many_arguments) ]
406
414
fn load_transaction_account < CB : TransactionProcessingCallback > (
407
415
callbacks : & CB ,
408
416
message : & impl SVMMessage ,
@@ -412,6 +420,7 @@ fn load_transaction_account<CB: TransactionProcessingCallback>(
412
420
account_overrides : Option < & AccountOverrides > ,
413
421
feature_set : & FeatureSet ,
414
422
rent_collector : & dyn SVMRentCollector ,
423
+ program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
415
424
loaded_programs : & ProgramCacheForTxBatch ,
416
425
) -> Result < ( LoadedTransactionAccount , bool ) > {
417
426
let mut account_found = true ;
@@ -439,14 +448,11 @@ fn load_transaction_account<CB: TransactionProcessingCallback>(
439
448
. then_some ( ( ) )
440
449
. and_then ( |_| loaded_programs. find ( account_key) )
441
450
{
442
- callbacks
443
- . get_account_shared_data ( account_key)
444
- . ok_or ( TransactionError :: AccountNotFound ) ?;
445
451
// Optimization to skip loading of accounts which are only used as
446
452
// programs in top-level instructions and not passed as instruction accounts.
447
453
LoadedTransactionAccount {
448
454
loaded_size : program. account_size ,
449
- account : account_shared_data_from_program ( & program ) ,
455
+ account : account_shared_data_from_program ( account_key , program_accounts ) ? ,
450
456
rent_collected : 0 ,
451
457
}
452
458
} else {
@@ -496,14 +502,20 @@ fn load_transaction_account<CB: TransactionProcessingCallback>(
496
502
Ok ( ( loaded_account, account_found) )
497
503
}
498
504
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 > {
500
509
// It's an executable program account. The program is already loaded in the cache.
501
510
// So the account data is not needed. Return a dummy AccountSharedData with meta
502
511
// information.
503
512
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) ;
505
517
program_account. set_executable ( true ) ;
506
- program_account
518
+ Ok ( program_account)
507
519
}
508
520
509
521
/// Accumulate loaded account data size into `accumulated_accounts_data_size`.
@@ -670,6 +682,7 @@ mod tests {
670
682
None ,
671
683
feature_set,
672
684
rent_collector,
685
+ & HashMap :: new ( ) ,
673
686
& ProgramCacheForTxBatch :: default ( ) ,
674
687
)
675
688
}
@@ -978,6 +991,7 @@ mod tests {
978
991
account_overrides,
979
992
& FeatureSet :: all_enabled ( ) ,
980
993
& RentCollector :: default ( ) ,
994
+ & HashMap :: new ( ) ,
981
995
& ProgramCacheForTxBatch :: default ( ) ,
982
996
)
983
997
}
@@ -1273,6 +1287,7 @@ mod tests {
1273
1287
None ,
1274
1288
& FeatureSet :: default ( ) ,
1275
1289
& RentCollector :: default ( ) ,
1290
+ & HashMap :: new ( ) ,
1276
1291
& loaded_programs,
1277
1292
) ;
1278
1293
@@ -1338,6 +1353,7 @@ mod tests {
1338
1353
None ,
1339
1354
& FeatureSet :: default ( ) ,
1340
1355
& RentCollector :: default ( ) ,
1356
+ & HashMap :: new ( ) ,
1341
1357
& loaded_programs,
1342
1358
) ;
1343
1359
@@ -1371,6 +1387,7 @@ mod tests {
1371
1387
let mut mock_bank = TestCallbacks :: default ( ) ;
1372
1388
let account_keypair = Keypair :: new ( ) ;
1373
1389
let program_keypair = Keypair :: new ( ) ;
1390
+ let loader_v2 = bpf_loader:: id ( ) ;
1374
1391
1375
1392
let mut account_data = AccountSharedData :: default ( ) ;
1376
1393
account_data. set_lamports ( 200 ) ;
@@ -1380,7 +1397,7 @@ mod tests {
1380
1397
1381
1398
let mut program_data = AccountSharedData :: default ( ) ;
1382
1399
program_data. set_lamports ( 200 ) ;
1383
- program_data. set_owner ( bpf_loader :: id ( ) ) ;
1400
+ program_data. set_owner ( loader_v2 ) ;
1384
1401
mock_bank
1385
1402
. accounts_map
1386
1403
. insert ( program_keypair. pubkey ( ) , program_data) ;
@@ -1391,7 +1408,7 @@ mod tests {
1391
1408
loader_data. set_owner ( native_loader:: id ( ) ) ;
1392
1409
mock_bank
1393
1410
. accounts_map
1394
- . insert ( bpf_loader :: id ( ) , loader_data. clone ( ) ) ;
1411
+ . insert ( loader_v2 , loader_data. clone ( ) ) ;
1395
1412
mock_bank
1396
1413
. accounts_map
1397
1414
. insert ( native_loader:: id ( ) , loader_data. clone ( ) ) ;
@@ -1408,6 +1425,8 @@ mod tests {
1408
1425
Hash :: default ( ) ,
1409
1426
) ) ;
1410
1427
1428
+ let mut program_accounts = HashMap :: new ( ) ;
1429
+ program_accounts. insert ( program_keypair. pubkey ( ) , ( & loader_v2, 0 ) ) ;
1411
1430
let mut loaded_programs = ProgramCacheForTxBatch :: default ( ) ;
1412
1431
loaded_programs. replenish (
1413
1432
program_keypair. pubkey ( ) ,
@@ -1431,12 +1450,13 @@ mod tests {
1431
1450
None ,
1432
1451
& FeatureSet :: default ( ) ,
1433
1452
& RentCollector :: default ( ) ,
1453
+ & program_accounts,
1434
1454
& loaded_programs,
1435
1455
) ;
1436
1456
1437
1457
// Executable flag is bypassed
1438
1458
let mut cached_program = AccountSharedData :: default ( ) ;
1439
- cached_program. set_owner ( bpf_loader :: id ( ) ) ;
1459
+ cached_program. set_owner ( loader_v2 ) ;
1440
1460
cached_program. set_executable ( true ) ;
1441
1461
1442
1462
assert_eq ! (
@@ -1445,7 +1465,7 @@ mod tests {
1445
1465
accounts: vec![
1446
1466
( account_keypair. pubkey( ) , account_data. clone( ) ) ,
1447
1467
( program_keypair. pubkey( ) , cached_program) ,
1448
- ( bpf_loader :: id ( ) , loader_data) ,
1468
+ ( loader_v2 , loader_data) ,
1449
1469
] ,
1450
1470
program_indices: vec![ vec![ 1 ] ] ,
1451
1471
rent: 0 ,
@@ -1478,6 +1498,7 @@ mod tests {
1478
1498
None ,
1479
1499
& FeatureSet :: default ( ) ,
1480
1500
& RentCollector :: default ( ) ,
1501
+ & program_accounts,
1481
1502
& loaded_programs,
1482
1503
) ;
1483
1504
@@ -1504,6 +1525,7 @@ mod tests {
1504
1525
None ,
1505
1526
& FeatureSet :: default ( ) ,
1506
1527
& RentCollector :: default ( ) ,
1528
+ & program_accounts,
1507
1529
& loaded_programs,
1508
1530
) ;
1509
1531
@@ -1553,6 +1575,7 @@ mod tests {
1553
1575
None ,
1554
1576
& FeatureSet :: default ( ) ,
1555
1577
& RentCollector :: default ( ) ,
1578
+ & HashMap :: new ( ) ,
1556
1579
& loaded_programs,
1557
1580
) ;
1558
1581
@@ -1598,6 +1621,7 @@ mod tests {
1598
1621
None ,
1599
1622
& FeatureSet :: default ( ) ,
1600
1623
& RentCollector :: default ( ) ,
1624
+ & HashMap :: new ( ) ,
1601
1625
& loaded_programs,
1602
1626
) ;
1603
1627
@@ -1655,6 +1679,7 @@ mod tests {
1655
1679
None ,
1656
1680
& FeatureSet :: default ( ) ,
1657
1681
& RentCollector :: default ( ) ,
1682
+ & HashMap :: new ( ) ,
1658
1683
& loaded_programs,
1659
1684
) ;
1660
1685
@@ -1718,6 +1743,7 @@ mod tests {
1718
1743
None ,
1719
1744
& FeatureSet :: default ( ) ,
1720
1745
& RentCollector :: default ( ) ,
1746
+ & HashMap :: new ( ) ,
1721
1747
& loaded_programs,
1722
1748
) ;
1723
1749
@@ -1772,6 +1798,7 @@ mod tests {
1772
1798
None ,
1773
1799
& FeatureSet :: default ( ) ,
1774
1800
& RentCollector :: default ( ) ,
1801
+ & HashMap :: new ( ) ,
1775
1802
& loaded_programs,
1776
1803
) ;
1777
1804
@@ -1836,6 +1863,7 @@ mod tests {
1836
1863
None ,
1837
1864
& FeatureSet :: default ( ) ,
1838
1865
& RentCollector :: default ( ) ,
1866
+ & HashMap :: new ( ) ,
1839
1867
& loaded_programs,
1840
1868
) ;
1841
1869
@@ -1924,6 +1952,7 @@ mod tests {
1924
1952
None ,
1925
1953
& FeatureSet :: default ( ) ,
1926
1954
& RentCollector :: default ( ) ,
1955
+ & HashMap :: new ( ) ,
1927
1956
& loaded_programs,
1928
1957
) ;
1929
1958
@@ -1989,6 +2018,7 @@ mod tests {
1989
2018
None ,
1990
2019
& FeatureSet :: default ( ) ,
1991
2020
& RentCollector :: default ( ) ,
2021
+ & HashMap :: new ( ) ,
1992
2022
& ProgramCacheForTxBatch :: default ( ) ,
1993
2023
) ;
1994
2024
@@ -2085,6 +2115,7 @@ mod tests {
2085
2115
None ,
2086
2116
& FeatureSet :: default ( ) ,
2087
2117
& RentCollector :: default ( ) ,
2118
+ & HashMap :: new ( ) ,
2088
2119
& loaded_programs,
2089
2120
) ;
2090
2121
@@ -2157,6 +2188,7 @@ mod tests {
2157
2188
None ,
2158
2189
& feature_set,
2159
2190
& rent_collector,
2191
+ & HashMap :: new ( ) ,
2160
2192
& ProgramCacheForTxBatch :: default ( ) ,
2161
2193
) ;
2162
2194
@@ -2178,6 +2210,7 @@ mod tests {
2178
2210
None ,
2179
2211
& feature_set,
2180
2212
& rent_collector,
2213
+ & HashMap :: new ( ) ,
2181
2214
& ProgramCacheForTxBatch :: default ( ) ,
2182
2215
) ;
2183
2216
@@ -2328,6 +2361,7 @@ mod tests {
2328
2361
None ,
2329
2362
& FeatureSet :: default ( ) ,
2330
2363
& RentCollector :: default ( ) ,
2364
+ & HashMap :: new ( ) ,
2331
2365
& ProgramCacheForTxBatch :: default ( ) ,
2332
2366
) ;
2333
2367
@@ -2355,6 +2389,8 @@ mod tests {
2355
2389
fn test_load_transaction_accounts_data_sizes ( ) {
2356
2390
let mut mock_bank = TestCallbacks :: default ( ) ;
2357
2391
2392
+ let loader_v2 = bpf_loader:: id ( ) ;
2393
+ let loader_v3 = bpf_loader_upgradeable:: id ( ) ;
2358
2394
let program1_keypair = Keypair :: new ( ) ;
2359
2395
let program1 = program1_keypair. pubkey ( ) ;
2360
2396
let program2 = Pubkey :: new_unique ( ) ;
@@ -2363,7 +2399,7 @@ mod tests {
2363
2399
2364
2400
let program2_size = std:: mem:: size_of :: < UpgradeableLoaderState > ( ) as u32 ;
2365
2401
let mut program2_account = AccountSharedData :: default ( ) ;
2366
- program2_account. set_owner ( bpf_loader_upgradeable :: id ( ) ) ;
2402
+ program2_account. set_owner ( loader_v3 ) ;
2367
2403
program2_account. set_executable ( true ) ;
2368
2404
program2_account. set_data ( vec ! [ 0 ; program2_size as usize ] ) ;
2369
2405
program2_account
@@ -2373,7 +2409,7 @@ mod tests {
2373
2409
. unwrap ( ) ;
2374
2410
mock_bank. accounts_map . insert ( program2, program2_account) ;
2375
2411
let mut programdata2_account = AccountSharedData :: default ( ) ;
2376
- programdata2_account. set_owner ( bpf_loader_upgradeable :: id ( ) ) ;
2412
+ programdata2_account. set_owner ( loader_v3 ) ;
2377
2413
programdata2_account. set_data ( vec ! [ 0 ; program2_size as usize ] ) ;
2378
2414
programdata2_account
2379
2415
. set_state ( & UpgradeableLoaderState :: ProgramData {
@@ -2423,12 +2459,14 @@ mod tests {
2423
2459
let ( account2_size, _) = make_account ( account2, program2, false ) ;
2424
2460
2425
2461
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 ) ;
2429
2464
2430
- let ( _program1_size, _) = make_account ( program1, bpf_loader :: id ( ) , true ) ;
2465
+ let ( _program1_size, _) = make_account ( program1, loader_v2 , true ) ;
2431
2466
2467
+ let mut program_accounts = HashMap :: new ( ) ;
2468
+ program_accounts. insert ( program1, ( & loader_v2, 0 ) ) ;
2469
+ program_accounts. insert ( program2, ( & loader_v3, 0 ) ) ;
2432
2470
let mut program_cache = ProgramCacheForTxBatch :: default ( ) ;
2433
2471
let program1_entry = ProgramCacheEntry {
2434
2472
account_size : 0 ,
@@ -2459,6 +2497,7 @@ mod tests {
2459
2497
None ,
2460
2498
& FeatureSet :: default ( ) ,
2461
2499
& RentCollector :: default ( ) ,
2500
+ & program_accounts,
2462
2501
& program_cache,
2463
2502
)
2464
2503
. unwrap ( ) ;
0 commit comments