@@ -26,16 +26,15 @@ use {
26
26
solana_address_lookup_table_program:: { error:: AddressLookupError , state:: AddressLookupTable } ,
27
27
solana_program_runtime:: {
28
28
compute_budget:: { self , ComputeBudget } ,
29
- loaded_programs:: { LoadedProgram , LoadedProgramType , LoadedProgramsForTxBatch } ,
29
+ loaded_programs:: LoadedProgramsForTxBatch ,
30
30
} ,
31
31
solana_sdk:: {
32
32
account:: { Account , AccountSharedData , ReadableAccount , WritableAccount } ,
33
33
account_utils:: StateMut ,
34
- bpf_loader_upgradeable,
34
+ bpf_loader_upgradeable:: { self , UpgradeableLoaderState } ,
35
35
clock:: { BankId , Slot } ,
36
36
feature_set:: {
37
- self , add_set_tx_loaded_accounts_data_size_instruction,
38
- delay_visibility_of_program_deployment, enable_request_heap_frame_ix,
37
+ self , add_set_tx_loaded_accounts_data_size_instruction, enable_request_heap_frame_ix,
39
38
include_loaded_accounts_data_size_in_fee_calculation,
40
39
remove_congestion_multiplier_from_fee_calculation, remove_deprecated_request_unit_ix,
41
40
simplify_writable_program_account_check, use_default_units_in_fee_calculation,
@@ -292,27 +291,8 @@ impl Accounts {
292
291
293
292
fn account_shared_data_from_program (
294
293
key : & Pubkey ,
295
- feature_set : & FeatureSet ,
296
- program : & LoadedProgram ,
297
294
program_accounts : & HashMap < Pubkey , ( & Pubkey , u64 ) > ,
298
295
) -> Result < AccountSharedData > {
299
- // Check for tombstone
300
- let result = match & program. program {
301
- LoadedProgramType :: FailedVerification ( _) | LoadedProgramType :: Closed => {
302
- Err ( TransactionError :: InvalidProgramForExecution )
303
- }
304
- LoadedProgramType :: DelayVisibility => {
305
- debug_assert ! ( feature_set. is_active( & delay_visibility_of_program_deployment:: id( ) ) ) ;
306
- Err ( TransactionError :: InvalidProgramForExecution )
307
- }
308
- _ => Ok ( ( ) ) ,
309
- } ;
310
- if feature_set. is_active ( & simplify_writable_program_account_check:: id ( ) ) {
311
- // Currently CPI only fails if an execution is actually attempted. With this check it
312
- // would also fail if a transaction just references an invalid program. So the checking
313
- // of the result is being feature gated.
314
- result?;
315
- }
316
296
// It's an executable program account. The program is already loaded in the cache.
317
297
// So the account data is not needed. Return a dummy AccountSharedData with meta
318
298
// information.
@@ -384,23 +364,21 @@ impl Accounts {
384
364
account_overrides. and_then ( |overrides| overrides. get ( key) )
385
365
{
386
366
( account_override. data ( ) . len ( ) , account_override. clone ( ) , 0 )
387
- } else if let Some ( program) = ( !instruction_account && !message. is_writable ( i) )
388
- . then_some ( ( ) )
389
- . and_then ( |_| loaded_programs. find ( key) )
367
+ } else if let Some ( program) = ( feature_set
368
+ . is_active ( & simplify_writable_program_account_check:: id ( ) )
369
+ && !instruction_account
370
+ && !message. is_writable ( i) )
371
+ . then_some ( ( ) )
372
+ . and_then ( |_| loaded_programs. find ( key) )
390
373
{
391
374
// This condition block does special handling for accounts that are passed
392
375
// as instruction account to any of the instructions in the transaction.
393
376
// It's been noticed that some programs are reading other program accounts
394
377
// (that are passed to the program as instruction accounts). So such accounts
395
378
// are needed to be loaded even though corresponding compiled program may
396
379
// already be present in the cache.
397
- Self :: account_shared_data_from_program (
398
- key,
399
- feature_set,
400
- program. as_ref ( ) ,
401
- program_accounts,
402
- )
403
- . map ( |program_account| ( program. account_size , program_account, 0 ) ) ?
380
+ Self :: account_shared_data_from_program ( key, program_accounts)
381
+ . map ( |program_account| ( program. account_size , program_account, 0 ) ) ?
404
382
} else {
405
383
self . accounts_db
406
384
. load_with_fixed_root ( ancestors, key)
@@ -456,17 +434,52 @@ impl Accounts {
456
434
validated_fee_payer = true ;
457
435
}
458
436
459
- if bpf_loader_upgradeable:: check_id ( account. owner ( ) ) {
460
- if !feature_set. is_active ( & simplify_writable_program_account_check:: id ( ) )
461
- && message. is_writable ( i)
462
- && !message. is_upgradeable_loader_present ( )
463
- {
437
+ if !feature_set. is_active ( & simplify_writable_program_account_check:: id ( ) ) {
438
+ if bpf_loader_upgradeable:: check_id ( account. owner ( ) ) {
439
+ if message. is_writable ( i) && !message. is_upgradeable_loader_present ( ) {
440
+ error_counters. invalid_writable_account += 1 ;
441
+ return Err ( TransactionError :: InvalidWritableAccount ) ;
442
+ }
443
+
444
+ if account. executable ( ) {
445
+ // The upgradeable loader requires the derived ProgramData account
446
+ if let Ok ( UpgradeableLoaderState :: Program {
447
+ programdata_address,
448
+ } ) = account. state ( )
449
+ {
450
+ if self
451
+ . accounts_db
452
+ . load_with_fixed_root ( ancestors, & programdata_address)
453
+ . is_none ( )
454
+ {
455
+ error_counters. account_not_found += 1 ;
456
+ return Err ( TransactionError :: ProgramAccountNotFound ) ;
457
+ }
458
+ } else {
459
+ error_counters. invalid_program_for_execution += 1 ;
460
+ return Err ( TransactionError :: InvalidProgramForExecution ) ;
461
+ }
462
+ }
463
+ } else if account. executable ( ) && message. is_writable ( i) {
464
464
error_counters. invalid_writable_account += 1 ;
465
465
return Err ( TransactionError :: InvalidWritableAccount ) ;
466
466
}
467
+ <<<<<<< HEAD
467
468
} else if account. executable ( ) && message. is_writable ( i) {
468
469
error_counters. invalid_writable_account += 1 ;
469
470
return Err ( TransactionError :: InvalidWritableAccount ) ;
471
+ =======
472
+ }
473
+
474
+ if in_reward_interval
475
+ && message. is_writable ( i)
476
+ && solana_stake_program:: check_id ( account. owner ( ) )
477
+ {
478
+ error_counters. program_execution_temporarily_restricted += 1 ;
479
+ return Err ( TransactionError :: ProgramExecutionTemporarilyRestricted {
480
+ account_index : i as u8 ,
481
+ } ) ;
482
+ >>>>>>> 3 f13cd353 ( Fix - LoadedProgramType :: Closed ( #31922 ) )
470
483
}
471
484
472
485
tx_rent += rent;
@@ -1478,7 +1491,6 @@ mod tests {
1478
1491
} ,
1479
1492
solana_sdk:: {
1480
1493
account:: { AccountSharedData , WritableAccount } ,
1481
- bpf_loader_upgradeable:: UpgradeableLoaderState ,
1482
1494
compute_budget:: ComputeBudgetInstruction ,
1483
1495
epoch_schedule:: EpochSchedule ,
1484
1496
genesis_config:: ClusterType ,
@@ -2477,8 +2489,12 @@ mod tests {
2477
2489
instructions,
2478
2490
) ;
2479
2491
let tx = Transaction :: new ( & [ & keypair] , message. clone ( ) , Hash :: default ( ) ) ;
2480
- let loaded_accounts =
2481
- load_accounts_with_excluded_features ( tx, & accounts, & mut error_counters, None ) ;
2492
+ let loaded_accounts = load_accounts_with_excluded_features (
2493
+ tx,
2494
+ & accounts,
2495
+ & mut error_counters,
2496
+ Some ( & [ simplify_writable_program_account_check:: id ( ) ] ) ,
2497
+ ) ;
2482
2498
2483
2499
assert_eq ! ( error_counters. invalid_writable_account, 1 ) ;
2484
2500
assert_eq ! ( loaded_accounts. len( ) , 1 ) ;
@@ -2491,8 +2507,12 @@ mod tests {
2491
2507
message. account_keys = vec ! [ key0, key1, key2] ; // revert key change
2492
2508
message. header . num_readonly_unsigned_accounts = 2 ; // mark both executables as readonly
2493
2509
let tx = Transaction :: new ( & [ & keypair] , message, Hash :: default ( ) ) ;
2494
- let loaded_accounts =
2495
- load_accounts_with_excluded_features ( tx, & accounts, & mut error_counters, None ) ;
2510
+ let loaded_accounts = load_accounts_with_excluded_features (
2511
+ tx,
2512
+ & accounts,
2513
+ & mut error_counters,
2514
+ Some ( & [ simplify_writable_program_account_check:: id ( ) ] ) ,
2515
+ ) ;
2496
2516
2497
2517
assert_eq ! ( error_counters. invalid_writable_account, 1 ) ;
2498
2518
assert_eq ! ( loaded_accounts. len( ) , 1 ) ;
0 commit comments