@@ -1498,6 +1498,192 @@ fn process_loader_upgradeable_instruction(
1498
1498
Ok ( ( ) )
1499
1499
}
1500
1500
1501
+ <<<<<<< HEAD
1502
+ =======
1503
+ fn common_extend_program (
1504
+ invoke_context : & mut InvokeContext ,
1505
+ additional_bytes : u32 ,
1506
+ check_authority : bool ,
1507
+ ) -> Result < ( ) , InstructionError > {
1508
+ let log_collector = invoke_context. get_log_collector ( ) ;
1509
+ let transaction_context = & invoke_context. transaction_context ;
1510
+ let instruction_context = transaction_context. get_current_instruction_context( ) ?;
1511
+ let program_id = instruction_context. get_last_program_key( transaction_context) ?;
1512
+
1513
+ const PROGRAM_DATA_ACCOUNT_INDEX : IndexOfAccount = 0 ;
1514
+ const PROGRAM_ACCOUNT_INDEX : IndexOfAccount = 1 ;
1515
+ const AUTHORITY_ACCOUNT_INDEX : IndexOfAccount = 2 ;
1516
+ // The unused `system_program_account_index` is 3 if `check_authority` and 2 otherwise.
1517
+ let optional_payer_account_index = if check_authority { 4 } else { 3 } ;
1518
+
1519
+ if additional_bytes == 0 {
1520
+ ic_logger_msg ! ( log_collector, "Additional bytes must be greater than 0" ) ;
1521
+ return Err ( InstructionError :: InvalidInstructionData ) ;
1522
+ }
1523
+
1524
+ let programdata_account = instruction_context
1525
+ . try_borrow_instruction_account( transaction_context, PROGRAM_DATA_ACCOUNT_INDEX ) ?;
1526
+ let programdata_key = * programdata_account. get_key( ) ;
1527
+
1528
+ if program_id != programdata_account. get_owner( ) {
1529
+ ic_logger_msg ! ( log_collector, "ProgramData owner is invalid" ) ;
1530
+ return Err ( InstructionError :: InvalidAccountOwner ) ;
1531
+ }
1532
+ if !programdata_account. is_writable( ) {
1533
+ ic_logger_msg ! ( log_collector, "ProgramData is not writable" ) ;
1534
+ return Err ( InstructionError :: InvalidArgument ) ;
1535
+ }
1536
+
1537
+ let program_account = instruction_context
1538
+ . try_borrow_instruction_account( transaction_context, PROGRAM_ACCOUNT_INDEX ) ?;
1539
+ if !program_account. is_writable( ) {
1540
+ ic_logger_msg ! ( log_collector, "Program account is not writable" ) ;
1541
+ return Err ( InstructionError :: InvalidArgument ) ;
1542
+ }
1543
+ if program_account. get_owner( ) != program_id {
1544
+ ic_logger_msg!( log_collector, "Program account not owned by loader" ) ;
1545
+ return Err ( InstructionError :: InvalidAccountOwner ) ;
1546
+ }
1547
+ let program_key = * program_account. get_key( ) ;
1548
+ match program_account. get_state( ) ? {
1549
+ UpgradeableLoaderState :: Program {
1550
+ programdata_address,
1551
+ } => {
1552
+ if programdata_address != programdata_key {
1553
+ ic_logger_msg!(
1554
+ log_collector,
1555
+ "Program account does not match ProgramData account"
1556
+ ) ;
1557
+ return Err ( InstructionError :: InvalidArgument ) ;
1558
+ }
1559
+ }
1560
+ _ => {
1561
+ ic_logger_msg ! ( log_collector, "Invalid Program account" ) ;
1562
+ return Err ( InstructionError :: InvalidAccountData ) ;
1563
+ }
1564
+ }
1565
+ drop( program_account) ;
1566
+
1567
+ let old_len = programdata_account. get_data( ) . len( ) ;
1568
+ let new_len = old_len. saturating_add( additional_bytes as usize ) ;
1569
+ if new_len > MAX_PERMITTED_DATA_LENGTH as usize {
1570
+ ic_logger_msg ! (
1571
+ log_collector,
1572
+ "Extended ProgramData length of {} bytes exceeds max account data length of {} bytes" ,
1573
+ new_len,
1574
+ MAX_PERMITTED_DATA_LENGTH
1575
+ ) ;
1576
+ return Err ( InstructionError :: InvalidRealloc ) ;
1577
+ }
1578
+
1579
+ let clock_slot = invoke_context
1580
+ . get_sysvar_cache( )
1581
+ . get_clock( )
1582
+ . map( |clock| clock. slot) ?;
1583
+
1584
+ let upgrade_authority_address = if let UpgradeableLoaderState :: ProgramData {
1585
+ slot,
1586
+ upgrade_authority_address,
1587
+ } = programdata_account. get_state( ) ?
1588
+ {
1589
+ if clock_slot == slot {
1590
+ ic_logger_msg!( log_collector, "Program was extended in this block already" ) ;
1591
+ return Err ( InstructionError :: InvalidArgument ) ;
1592
+ }
1593
+
1594
+ if upgrade_authority_address. is_none( ) {
1595
+ ic_logger_msg ! (
1596
+ log_collector,
1597
+ "Cannot extend ProgramData accounts that are not upgradeable"
1598
+ ) ;
1599
+ return Err ( InstructionError :: Immutable ) ;
1600
+ }
1601
+
1602
+ if check_authority {
1603
+ let authority_key = Some (
1604
+ * transaction_context. get_key_of_account_at_index(
1605
+ instruction_context
1606
+ . get_index_of_instruction_account_in_transaction( AUTHORITY_ACCOUNT_INDEX ) ?,
1607
+ ) ?,
1608
+ ) ;
1609
+ if upgrade_authority_address != authority_key {
1610
+ ic_logger_msg!( log_collector, "Incorrect upgrade authority provided" ) ;
1611
+ return Err ( InstructionError :: IncorrectAuthority ) ;
1612
+ }
1613
+ if !instruction_context. is_instruction_account_signer( AUTHORITY_ACCOUNT_INDEX ) ? {
1614
+ ic_logger_msg!( log_collector, "Upgrade authority did not sign") ;
1615
+ return Err ( InstructionError :: MissingRequiredSignature ) ;
1616
+ }
1617
+ }
1618
+
1619
+ upgrade_authority_address
1620
+ } else {
1621
+ ic_logger_msg!( log_collector, "ProgramData state is invalid") ;
1622
+ return Err ( InstructionError :: InvalidAccountData ) ;
1623
+ } ;
1624
+
1625
+ let required_payment = {
1626
+ let balance = programdata_account. get_lamports( ) ;
1627
+ let rent = invoke_context. get_sysvar_cache( ) . get_rent( ) ?;
1628
+ let min_balance = rent. minimum_balance( new_len) . max( 1 ) ;
1629
+ min_balance. saturating_sub( balance)
1630
+ } ;
1631
+
1632
+ // Borrowed accounts need to be dropped before native_invoke
1633
+ drop( programdata_account) ;
1634
+
1635
+ // Dereference the program ID to prevent overlapping mutable/immutable borrow of invoke context
1636
+ let program_id = * program_id;
1637
+ if required_payment > 0 {
1638
+ let payer_key = * transaction_context. get_key_of_account_at_index(
1639
+ instruction_context
1640
+ . get_index_of_instruction_account_in_transaction( optional_payer_account_index) ?,
1641
+ ) ?;
1642
+
1643
+ invoke_context. native_invoke(
1644
+ system_instruction:: transfer( & payer_key, & programdata_key, required_payment) . into( ) ,
1645
+ & [ ] ,
1646
+ ) ?;
1647
+ }
1648
+
1649
+ let transaction_context = & invoke_context. transaction_context ;
1650
+ let instruction_context = transaction_context. get_current_instruction_context ( ) ?;
1651
+ let mut programdata_account = instruction_context
1652
+ . try_borrow_instruction_account ( transaction_context, PROGRAM_DATA_ACCOUNT_INDEX ) ?;
1653
+ programdata_account. set_data_length ( new_len) ?;
1654
+
1655
+ let programdata_data_offset = UpgradeableLoaderState :: size_of_programdata_metadata ( ) ;
1656
+
1657
+ deploy_program ! (
1658
+ invoke_context,
1659
+ & program_key,
1660
+ & program_id,
1661
+ UpgradeableLoaderState :: size_of_program( ) . saturating_add( new_len) ,
1662
+ programdata_account
1663
+ . get_data( )
1664
+ . get( programdata_data_offset..)
1665
+ . ok_or( InstructionError :: AccountDataTooSmall ) ?,
1666
+ clock_slot,
1667
+ ) ;
1668
+ drop ( programdata_account) ;
1669
+
1670
+ let mut programdata_account = instruction_context
1671
+ . try_borrow_instruction_account ( transaction_context, PROGRAM_DATA_ACCOUNT_INDEX ) ?;
1672
+ programdata_account. set_state ( & UpgradeableLoaderState :: ProgramData {
1673
+ slot : clock_slot,
1674
+ upgrade_authority_address,
1675
+ } ) ?;
1676
+
1677
+ ic_logger_msg ! (
1678
+ log_collector,
1679
+ "Extended ProgramData account by {} bytes" ,
1680
+ additional_bytes
1681
+ ) ;
1682
+
1683
+ Ok ( ( ) )
1684
+ }
1685
+
1686
+ >>>>>>> 0 c1d60ddd ( Fix - Reformulates code comment in natural language ( #6337 ) )
1501
1687
fn common_close_account (
1502
1688
authority_address: & Option <Pubkey >,
1503
1689
transaction_context: & TransactionContext ,
0 commit comments