@@ -13381,6 +13381,184 @@ fn test_deploy_last_epoch_slot() {
13381
13381
assert_eq ! ( result_with_feature_enabled, Ok ( ( ) ) ) ;
13382
13382
}
13383
13383
13384
+ #[ test]
13385
+ fn test_loader_v3_to_v4_migration ( ) {
13386
+ solana_logger:: setup ( ) ;
13387
+
13388
+ // Bank Setup
13389
+ let ( mut genesis_config, mint_keypair) = create_genesis_config ( 1_000_000 * LAMPORTS_PER_SOL ) ;
13390
+ activate_feature (
13391
+ & mut genesis_config,
13392
+ solana_feature_set:: enable_loader_v4:: id ( ) ,
13393
+ ) ;
13394
+ let mut bank = Bank :: new_for_tests ( & genesis_config) ;
13395
+ bank. activate_feature ( & feature_set:: remove_accounts_executable_flag_checks:: id ( ) ) ;
13396
+ let ( bank, bank_forks) = bank. wrap_with_bank_forks_for_tests ( ) ;
13397
+ let fee_calculator = genesis_config. fee_rate_governor . create_fee_calculator ( ) ;
13398
+
13399
+ // deploy a program
13400
+ let mut file = File :: open ( "../programs/bpf_loader/test_elfs/out/noop_aligned.so" ) . unwrap ( ) ;
13401
+ let mut elf = Vec :: new ( ) ;
13402
+ file. read_to_end ( & mut elf) . unwrap ( ) ;
13403
+
13404
+ let program_keypair = Keypair :: new ( ) ;
13405
+ let ( programdata_address, _) = Pubkey :: find_program_address (
13406
+ & [ program_keypair. pubkey ( ) . as_ref ( ) ] ,
13407
+ & bpf_loader_upgradeable:: id ( ) ,
13408
+ ) ;
13409
+ let payer_keypair = Keypair :: new ( ) ;
13410
+ let upgrade_authority_keypair = Keypair :: new ( ) ;
13411
+ let migration_authority_keypair = & upgrade_authority_keypair;
13412
+
13413
+ let min_program_balance =
13414
+ bank. get_minimum_balance_for_rent_exemption ( UpgradeableLoaderState :: size_of_program ( ) ) ;
13415
+ let mut program_account = AccountSharedData :: new (
13416
+ min_program_balance,
13417
+ UpgradeableLoaderState :: size_of_program ( ) ,
13418
+ & bpf_loader_upgradeable:: id ( ) ,
13419
+ ) ;
13420
+ program_account
13421
+ . set_state ( & UpgradeableLoaderState :: Program {
13422
+ programdata_address,
13423
+ } )
13424
+ . unwrap ( ) ;
13425
+
13426
+ let mut closed_programdata_account = AccountSharedData :: new (
13427
+ 0 ,
13428
+ UpgradeableLoaderState :: size_of_programdata_metadata ( ) ,
13429
+ & bpf_loader_upgradeable:: id ( ) ,
13430
+ ) ;
13431
+ closed_programdata_account
13432
+ . set_state ( & UpgradeableLoaderState :: ProgramData {
13433
+ slot : 0 ,
13434
+ upgrade_authority_address : None ,
13435
+ } )
13436
+ . unwrap ( ) ;
13437
+ let message = Message :: new (
13438
+ & [ bpf_loader_upgradeable:: migrate_program (
13439
+ & programdata_address,
13440
+ & program_keypair. pubkey ( ) ,
13441
+ & program_keypair. pubkey ( ) ,
13442
+ ) ] ,
13443
+ Some ( & payer_keypair. pubkey ( ) ) ,
13444
+ ) ;
13445
+ let signers = & [ & payer_keypair, & program_keypair] ;
13446
+ let closed_migration_transaction =
13447
+ Transaction :: new ( signers, message. clone ( ) , bank. last_blockhash ( ) ) ;
13448
+
13449
+ let mut finalized_programdata_account = AccountSharedData :: new (
13450
+ 0 ,
13451
+ UpgradeableLoaderState :: size_of_programdata ( elf. len ( ) ) ,
13452
+ & bpf_loader_upgradeable:: id ( ) ,
13453
+ ) ;
13454
+ finalized_programdata_account
13455
+ . set_state ( & UpgradeableLoaderState :: ProgramData {
13456
+ slot : 0 ,
13457
+ upgrade_authority_address : None ,
13458
+ } )
13459
+ . unwrap ( ) ;
13460
+ finalized_programdata_account
13461
+ . data_as_mut_slice ( )
13462
+ . get_mut ( UpgradeableLoaderState :: size_of_programdata_metadata ( ) ..)
13463
+ . unwrap ( )
13464
+ . copy_from_slice ( & elf) ;
13465
+ let message = Message :: new (
13466
+ & [ bpf_loader_upgradeable:: migrate_program (
13467
+ & programdata_address,
13468
+ & program_keypair. pubkey ( ) ,
13469
+ & program_keypair. pubkey ( ) ,
13470
+ ) ] ,
13471
+ Some ( & payer_keypair. pubkey ( ) ) ,
13472
+ ) ;
13473
+ let signers = & [ & payer_keypair, & program_keypair] ;
13474
+ let finalized_migration_transaction =
13475
+ Transaction :: new ( signers, message. clone ( ) , bank. last_blockhash ( ) ) ;
13476
+
13477
+ let mut upgradeable_programdata_account = AccountSharedData :: new (
13478
+ 0 ,
13479
+ UpgradeableLoaderState :: size_of_programdata ( elf. len ( ) ) ,
13480
+ & bpf_loader_upgradeable:: id ( ) ,
13481
+ ) ;
13482
+ upgradeable_programdata_account
13483
+ . set_state ( & UpgradeableLoaderState :: ProgramData {
13484
+ slot : 0 ,
13485
+ upgrade_authority_address : Some ( upgrade_authority_keypair. pubkey ( ) ) ,
13486
+ } )
13487
+ . unwrap ( ) ;
13488
+ upgradeable_programdata_account
13489
+ . data_as_mut_slice ( )
13490
+ . get_mut ( UpgradeableLoaderState :: size_of_programdata_metadata ( ) ..)
13491
+ . unwrap ( )
13492
+ . copy_from_slice ( & elf) ;
13493
+ let message = Message :: new (
13494
+ & [ bpf_loader_upgradeable:: migrate_program (
13495
+ & programdata_address,
13496
+ & program_keypair. pubkey ( ) ,
13497
+ & migration_authority_keypair. pubkey ( ) ,
13498
+ ) ] ,
13499
+ Some ( & payer_keypair. pubkey ( ) ) ,
13500
+ ) ;
13501
+ let signers = & [ & payer_keypair, migration_authority_keypair] ;
13502
+ let upgradeable_migration_transaction =
13503
+ Transaction :: new ( signers, message. clone ( ) , bank. last_blockhash ( ) ) ;
13504
+
13505
+ let mut next_slot = 1 ;
13506
+ for ( mut programdata_account, transaction, expected_execution_result) in [
13507
+ (
13508
+ closed_programdata_account,
13509
+ closed_migration_transaction,
13510
+ Err ( TransactionError :: InstructionError (
13511
+ 0 ,
13512
+ InstructionError :: InvalidInstructionData ,
13513
+ ) ) ,
13514
+ ) ,
13515
+ (
13516
+ finalized_programdata_account,
13517
+ finalized_migration_transaction,
13518
+ Ok ( ( ) ) ,
13519
+ ) ,
13520
+ (
13521
+ upgradeable_programdata_account,
13522
+ upgradeable_migration_transaction,
13523
+ Ok ( ( ) ) ,
13524
+ ) ,
13525
+ ] {
13526
+ let bank = new_bank_from_parent_with_bank_forks (
13527
+ & bank_forks,
13528
+ bank. clone ( ) ,
13529
+ & Pubkey :: default ( ) ,
13530
+ next_slot,
13531
+ ) ;
13532
+ next_slot += 1 ;
13533
+
13534
+ let min_programdata_balance =
13535
+ bank. get_minimum_balance_for_rent_exemption ( programdata_account. data ( ) . len ( ) ) ;
13536
+ programdata_account. set_lamports ( min_programdata_balance) ;
13537
+ let payer_balance = min_program_balance
13538
+ . saturating_add ( min_programdata_balance)
13539
+ . saturating_add ( LAMPORTS_PER_SOL )
13540
+ . saturating_add ( fee_calculator. lamports_per_signature ) ;
13541
+ let payer_account = AccountSharedData :: new ( payer_balance, 0 , & system_program:: id ( ) ) ;
13542
+ bank. store_account ( & program_keypair. pubkey ( ) , & program_account) ;
13543
+ bank. store_account ( & programdata_address, & programdata_account) ;
13544
+ bank. store_account ( & payer_keypair. pubkey ( ) , & payer_account) ;
13545
+ let result = bank. process_transaction ( & transaction) ;
13546
+ assert ! ( result. is_ok( ) , "result: {:?}" , result) ;
13547
+
13548
+ goto_end_of_slot ( bank. clone ( ) ) ;
13549
+ let bank =
13550
+ new_bank_from_parent_with_bank_forks ( & bank_forks, bank, & Pubkey :: default ( ) , next_slot) ;
13551
+ next_slot += 1 ;
13552
+
13553
+ let instruction = Instruction :: new_with_bytes ( program_keypair. pubkey ( ) , & [ ] , Vec :: new ( ) ) ;
13554
+ let message = Message :: new ( & [ instruction] , Some ( & mint_keypair. pubkey ( ) ) ) ;
13555
+ let binding = mint_keypair. insecure_clone ( ) ;
13556
+ let transaction = Transaction :: new ( & [ & binding] , message, bank. last_blockhash ( ) ) ;
13557
+ let execution_result = bank. process_transaction ( & transaction) ;
13558
+ assert_eq ! ( execution_result, expected_execution_result) ;
13559
+ }
13560
+ }
13561
+
13384
13562
#[ test]
13385
13563
fn test_blockhash_last_valid_block_height ( ) {
13386
13564
let genesis_config = GenesisConfig :: default ( ) ;
0 commit comments