LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_address_lookup_table_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 674 0.0 %
Date: 2026-01-23 05:02:40 Functions: 0 13 0.0 %

          Line data    Source code
       1             : #include "fd_address_lookup_table_program.h"
       2             : #include "../fd_executor.h"
       3             : #include "../fd_pubkey_utils.h"
       4             : #include "../fd_borrowed_account.h"
       5             : #include "../sysvar/fd_sysvar_slot_hashes.h"
       6             : #include "../../vm/syscall/fd_vm_syscall.h"
       7             : #include "fd_native_cpi.h"
       8             : #include "../fd_runtime_err.h"
       9             : #include "../fd_system_ids.h"
      10             : 
      11             : #include <string.h>
      12             : 
      13             : /* The worst case address lookup table footprint is for the extend
      14             :    instruction which is dynamically sized based on the number of new
      15             :    entries.  Assuming that the instruction takes up the full transaction
      16             :    MTU (1232 bytes), we can have 1232/32 entries = 38 entries.  This is
      17             :    not the tightest bound possible, but it is reasonable.
      18             :    The total footprint is then sizeof(fd_addrlut_instruction_t) + 38
      19             :    entries * sizeof(fd_pubkey_t) = 1240 bytes. */
      20             : 
      21             : #define FD_ADDRLUT_INSTR_FOOTPRINT (1240UL)
      22             : 
      23             : struct fd_addrlut {
      24             :   fd_address_lookup_table_state_t state;
      25             : 
      26             :   fd_pubkey_t const * addr;  /* points into account data */
      27             :   ulong               addr_cnt;
      28             : };
      29             : 
      30             : typedef struct fd_addrlut fd_addrlut_t;
      31             : 
      32           0 : #define FD_ADDRLUT_META_SZ       (56UL)
      33           0 : #define FD_ADDRLUT_MAX_ADDR_CNT (256UL)
      34             : #define DEFAULT_COMPUTE_UNITS   (750UL)
      35           0 : #define MAX_ENTRIES             FD_SYSVAR_SLOT_HASHES_CAP
      36             : 
      37             : static fd_addrlut_t *
      38           0 : fd_addrlut_new( void * mem ) {
      39             : 
      40           0 :   if( FD_UNLIKELY( !mem ) ) {
      41           0 :     FD_LOG_WARNING(( "NULL mem" ));
      42           0 :     return NULL;
      43           0 :   }
      44             : 
      45           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_addrlut_t) ) ) ) {
      46           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      47           0 :     return NULL;
      48           0 :   }
      49             : 
      50           0 :   return fd_type_pun( mem );
      51           0 : }
      52             : 
      53             : static int
      54             : fd_addrlut_deserialize( fd_addrlut_t * lut,
      55             :                         uchar const *  data,
      56           0 :                         ulong          data_sz ) {
      57             : 
      58           0 :   lut = fd_addrlut_new( lut ); FD_TEST( lut );
      59             : 
      60             :   /* We anticipate that we require no allocations to decode the address lookup
      61             :      table state size and that the data is already preallocated. */
      62           0 :   fd_bincode_decode_ctx_t decode = {
      63           0 :     .data    = data,
      64           0 :     .dataend = data+data_sz
      65           0 :   };
      66             : 
      67           0 :   ulong total_sz = 0UL;
      68           0 :   if( FD_UNLIKELY( fd_address_lookup_table_state_decode_footprint( &decode, &total_sz )!=FD_BINCODE_SUCCESS ) ) {
      69           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      70           0 :   }
      71             : 
      72             :   /* NOTE: We technically don't need this check if we assume that the caller
      73             :      is correctly handling the memory that is passed into this function. */
      74           0 :   if( FD_UNLIKELY( total_sz!=sizeof(fd_address_lookup_table_state_t) ) ) {
      75           0 :     FD_LOG_ERR(( "Unexpected total size of address lookup table state" ));
      76           0 :   }
      77             : 
      78           0 :   fd_address_lookup_table_state_decode( &lut->state, &decode );
      79             : 
      80           0 :   if( lut->state.discriminant==fd_address_lookup_table_state_enum_uninitialized )
      81           0 :     return FD_EXECUTOR_INSTR_ERR_UNINITIALIZED_ACCOUNT;
      82           0 :   FD_TEST( lut->state.discriminant == fd_address_lookup_table_state_enum_lookup_table );
      83             : 
      84           0 :   if( data_sz < FD_ADDRLUT_META_SZ )
      85           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      86             : 
      87           0 :   uchar const * raw_addr_data    = data   +FD_ADDRLUT_META_SZ;
      88           0 :   ulong         raw_addr_data_sz = data_sz-FD_ADDRLUT_META_SZ;
      89             : 
      90           0 :   if( !fd_ulong_is_aligned( raw_addr_data_sz, 32UL ) )
      91           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      92             : 
      93           0 :   lut->addr     = fd_type_pun_const( raw_addr_data );
      94           0 :   lut->addr_cnt = raw_addr_data_sz / 32UL;
      95             : 
      96           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
      97           0 : }
      98             : 
      99             : static int
     100             : fd_addrlut_serialize_meta( fd_address_lookup_table_state_t const * state,
     101             :                            uchar * data,
     102           0 :                            ulong   data_sz ) {
     103             : 
     104             :   /* TODO can this ever get hit?  All code paths to this function seem
     105             :      to check account data size during deserialization. */
     106           0 :   if( FD_UNLIKELY( data_sz<FD_ADDRLUT_META_SZ ) )
     107           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     108             : 
     109           0 :   fd_bincode_encode_ctx_t encode =
     110           0 :     { .data    = data,
     111           0 :       .dataend = data+FD_ADDRLUT_META_SZ };
     112           0 :   fd_memset( data, 0, (ulong)encode.dataend - (ulong)encode.data );
     113             : 
     114           0 :   int bin_err = fd_address_lookup_table_state_encode( state, &encode );
     115           0 :   FD_TEST( !bin_err );
     116             : 
     117           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     118           0 : }
     119             : 
     120             : static ulong
     121             : slot_hashes_position( fd_slot_hash_t const * hashes, /* deque */
     122           0 :                       ulong                  slot ) {
     123             :   /* Logic is copied from slice::binary_search_by() in Rust. While not fully optimized,
     124             :      it aims to achieve fuzzing conformance for both sorted and unsorted inputs.
     125             :      Returns the slot hash position of the input slot. */
     126           0 :   ulong size = deq_fd_slot_hash_t_cnt( hashes );
     127           0 :   if( FD_UNLIKELY( size==0UL ) ) return ULONG_MAX;
     128             : 
     129           0 :   ulong base = 0UL;
     130           0 :   while( size>1UL ) {
     131           0 :     ulong half = size / 2UL;
     132           0 :     ulong mid = base + half;
     133           0 :     ulong mid_slot = deq_fd_slot_hash_t_peek_index_const( hashes, mid )->slot;
     134           0 :     base = (slot>mid_slot) ? base : mid;
     135           0 :     size -= half;
     136           0 :   }
     137             : 
     138           0 :   return deq_fd_slot_hash_t_peek_index_const( hashes, base )->slot==slot ? base : ULONG_MAX;
     139           0 : }
     140             : 
     141             : /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L81-L104 */
     142             : static uchar
     143             : fd_addrlut_status( fd_lookup_table_meta_t const * state,
     144             :                    ulong                          current_slot,
     145             :                    fd_slot_hash_t const *         slot_hashes, /* deque */
     146           0 :                    ulong *                        remaining_blocks ) {
     147             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L82-L83 */
     148           0 :   if( state->deactivation_slot==ULONG_MAX ) {
     149           0 :     return FD_ADDRLUT_STATUS_ACTIVATED;
     150           0 :   }
     151             : 
     152             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L84-L87 */
     153           0 :   if( state->deactivation_slot==current_slot ) {
     154           0 :     *remaining_blocks = MAX_ENTRIES + 1UL;
     155           0 :     return FD_ADDRLUT_STATUS_DEACTIVATING;
     156           0 :   }
     157             : 
     158             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L88-L100 */
     159           0 :   ulong slot_hash_position = slot_hashes_position( slot_hashes, state->deactivation_slot );
     160           0 :   if( slot_hash_position!=ULONG_MAX ) {
     161           0 :     *remaining_blocks = MAX_ENTRIES - slot_hash_position;
     162           0 :     return FD_ADDRLUT_STATUS_DEACTIVATING;
     163           0 :   }
     164             : 
     165             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L102 */
     166           0 :   return FD_ADDRLUT_STATUS_DEACTIVATED;
     167           0 : }
     168             : 
     169             : /* Note on uses of fd_borrowed_account_acquire_write_is_safe:
     170             : 
     171             :    In some places of this program, the Agave implementation acquires a
     172             :    "mutable borrow" on the account that is immediately dropped before
     173             :    any borrow can occur.  In other words, this borrow attempt only
     174             :    introduces a "borrow failed" error case into the protocol but
     175             :    otherwise introduces no side effects.  i.e.
     176             : 
     177             :      if not fd_borrowed_account_acquire_write():
     178             :        return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED
     179             :      ... read only operations ...
     180             :      fd_borrowed_account_release_write()
     181             :      ... arbitrary logic ...
     182             : 
     183             :    Is equivalent to
     184             : 
     185             :      if not fd_borrowed_account_acquire_write_is_safe():
     186             :        return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED
     187             :      ... read only operations ...
     188             :      ... arbitrary logic ... */
     189             : 
     190             : static int
     191             : create_lookup_table( fd_exec_instr_ctx_t *       ctx,
     192           0 :                      fd_addrlut_create_t const * create ) {
     193             : 
     194           0 : # define ACC_IDX_LUT       (0UL)
     195           0 : # define ACC_IDX_AUTHORITY (1UL)
     196           0 : # define ACC_IDX_PAYER     (2UL)
     197             : 
     198           0 :   int err;
     199             : 
     200           0 :   ulong               lut_lamports  = 0UL;
     201           0 :   fd_pubkey_t const * lut_key       = NULL;
     202           0 :   fd_pubkey_t const * lut_owner     = NULL;
     203           0 :   fd_pubkey_t const * authority_key = NULL;
     204           0 :   fd_pubkey_t const * payer_key     = NULL;
     205             : 
     206             :   /* Prepare LUT account **********************************************/
     207             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L59-L60 */
     208             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
     209           0 :   fd_guarded_borrowed_account_t lut_acct = {0};
     210           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     211             : 
     212             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L60-L62 */
     213           0 :   lut_lamports = fd_borrowed_account_get_lamports( &lut_acct );
     214           0 :   lut_key      = lut_acct.pubkey;
     215           0 :   lut_owner    = fd_borrowed_account_get_owner( &lut_acct );
     216             : 
     217             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L72 */
     218           0 :   fd_borrowed_account_drop( &lut_acct );
     219             : 
     220             :   /* Prepare authority account ****************************************/
     221             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L74-L75 */
     222             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
     223           0 :   fd_guarded_borrowed_account_t authority_acct = {0};
     224           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_AUTHORITY, &authority_acct );
     225             : 
     226             : 
     227             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L75 */
     228           0 :   authority_key = authority_acct.pubkey;
     229             : 
     230             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L85 */
     231           0 :   fd_borrowed_account_drop( &authority_acct );
     232             : 
     233             :   /* Prepare payer account ********************************************/
     234             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L87-L88 */
     235             :     /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     236           0 :   fd_guarded_borrowed_account_t payer_acct = {0};
     237           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_PAYER, &payer_acct );
     238             : 
     239           0 :   payer_key = payer_acct.pubkey;
     240             : 
     241             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L89-L92 */
     242           0 :   if( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_PAYER, NULL ) ) {
     243           0 :     fd_log_collector_msg_literal( ctx, "Payer account must be a signer" );
     244           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     245           0 :   }
     246             : 
     247             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L94 */
     248           0 :   fd_borrowed_account_drop( &payer_acct );
     249             : 
     250           0 :   ulong derivation_slot = 1UL;
     251             : 
     252           0 :   do {
     253           0 :     fd_slot_hash_t const * slot_hash = fd_sysvar_cache_slot_hashes_join_const( ctx->sysvar_cache );
     254           0 :     if( FD_UNLIKELY( !slot_hash ) ) {
     255           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     256           0 :     }
     257             : 
     258             :     /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L97 */
     259           0 :     ulong is_recent_slot = slot_hashes_position( slot_hash, create->recent_slot )!=ULONG_MAX;
     260           0 :     fd_sysvar_cache_slot_hashes_leave_const( ctx->sysvar_cache, slot_hash );
     261           0 :     if( FD_UNLIKELY( !is_recent_slot ) ) {
     262             :       /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L100-L105 */
     263             :       /* Max msg_sz: 24 - 3 + 20 = 41 < 127 => we can use printf */
     264           0 :       fd_log_collector_printf_dangerous_max_127( ctx, "%lu is not a recent slot", create->recent_slot );
     265           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     266           0 :     } else {
     267           0 :       derivation_slot = create->recent_slot;
     268           0 :     }
     269           0 :   } while(0);
     270             : 
     271             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L109-L118 */
     272           0 :   fd_pubkey_t derived_tbl_key[1];
     273           0 :   uchar const * seeds[2];
     274           0 :   ulong         seed_szs[2] = { sizeof(fd_pubkey_t), sizeof(ulong) };
     275           0 :   seeds[0] = (uchar const *)authority_key;
     276           0 :   seeds[1] = (uchar const *)&derivation_slot;
     277           0 :   err = fd_pubkey_derive_pda( &fd_solana_address_lookup_table_program_id, 2UL, seeds,
     278           0 :                                   seed_szs, (uchar*)&create->bump_seed, derived_tbl_key, &ctx->txn_out->err.custom_err );
     279           0 :   if( FD_UNLIKELY( err ) ) {
     280           0 :     return err;
     281           0 :   }
     282             : 
     283             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L120-L127 */
     284           0 :   if( FD_UNLIKELY( 0!=memcmp( lut_key->key, derived_tbl_key->key, sizeof(fd_pubkey_t) ) ) ) {
     285             :     /* Max msg_sz: 44 - 2 + 45 = 87 < 127 => we can use printf */
     286           0 :     FD_BASE58_ENCODE_32_BYTES( derived_tbl_key->uc, derived_tbl_key_b58 );
     287           0 :     fd_log_collector_printf_dangerous_max_127( ctx,
     288           0 :       "Table address must match derived address: %s", derived_tbl_key_b58 );
     289           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     290           0 :   }
     291             : 
     292             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L129-L135 */
     293           0 :   if( 0==memcmp( lut_owner, fd_solana_address_lookup_table_program_id.key, sizeof(fd_pubkey_t) ) ) {
     294           0 :     return FD_EXECUTOR_INSTR_SUCCESS;
     295           0 :   }
     296             : 
     297             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L137-L142 */
     298             : 
     299           0 :   fd_rent_t const rent = fd_sysvar_cache_rent_read_nofail( ctx->sysvar_cache );
     300           0 :   ulong tbl_acct_data_len = 0x38UL;
     301           0 :   ulong required_lamports = fd_rent_exempt_minimum_balance( &rent, tbl_acct_data_len );
     302           0 :   /* */ required_lamports = fd_ulong_max( required_lamports, 1UL );
     303           0 :   /* */ required_lamports = fd_ulong_sat_sub( required_lamports, lut_lamports );
     304             : 
     305             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L144-L149 */
     306           0 :   if( required_lamports>0UL ) {
     307             :     // Create account metas
     308           0 :     fd_vm_rust_account_meta_t acct_metas[ 2UL ];
     309           0 :     fd_native_cpi_create_account_meta( payer_key, 1, 1, &acct_metas[0] );
     310           0 :     fd_native_cpi_create_account_meta( lut_key,   0, 1, &acct_metas[1] );
     311             : 
     312             :     // Create signers list
     313           0 :     fd_pubkey_t signers[16];
     314           0 :     ulong signers_cnt = 1;
     315           0 :     signers[0] = *payer_key;
     316             : 
     317             :     // Create system program instruction
     318           0 :     uchar instr_data[FD_TXN_MTU];
     319           0 :     fd_system_program_instruction_t instr = {
     320           0 :       .discriminant = fd_system_program_instruction_enum_transfer,
     321           0 :       .inner = {
     322           0 :         .transfer = required_lamports,
     323           0 :       }
     324           0 :     };
     325             : 
     326           0 :     fd_bincode_encode_ctx_t encode_ctx = {
     327           0 :       .data    = instr_data,
     328           0 :       .dataend = instr_data + FD_TXN_MTU
     329           0 :     };
     330             : 
     331             :     // This should never fail.
     332           0 :     int err = fd_system_program_instruction_encode( &instr, &encode_ctx );
     333           0 :     if( FD_UNLIKELY( err ) ) {
     334           0 :       return FD_EXECUTOR_INSTR_ERR_FATAL;
     335           0 :     }
     336             : 
     337           0 :     ulong instr_data_sz = (ulong)( (uchar *)encode_ctx.data - instr_data );
     338           0 :     err = fd_native_cpi_native_invoke( ctx,
     339           0 :                                        &fd_solana_system_program_id,
     340           0 :                                        instr_data,
     341           0 :                                        instr_data_sz,
     342           0 :                                        acct_metas,
     343           0 :                                        2UL,
     344           0 :                                        signers,
     345           0 :                                        signers_cnt );
     346           0 :     if( FD_UNLIKELY( err ) ) {
     347           0 :       return err;
     348           0 :     }
     349           0 :   }
     350             : 
     351           0 :   fd_vm_rust_account_meta_t acct_metas[ 1UL ];
     352           0 :   fd_native_cpi_create_account_meta( lut_key, 1, 1, acct_metas );
     353             : 
     354             :   // Create signers list
     355           0 :   fd_pubkey_t signers[16];
     356           0 :   ulong signers_cnt = 1;
     357           0 :   signers[0] = *lut_key;
     358             : 
     359             :   // Create system program allocate instruction
     360           0 :   uchar instr_data[FD_TXN_MTU];
     361           0 :   fd_system_program_instruction_t instr = {
     362           0 :     .discriminant = fd_system_program_instruction_enum_allocate,
     363           0 :     .inner = {
     364           0 :       .allocate = FD_LOOKUP_TABLE_META_SIZE,
     365           0 :     }
     366           0 :   };
     367             : 
     368           0 :   fd_bincode_encode_ctx_t encode_ctx = {
     369           0 :     .data    = instr_data,
     370           0 :     .dataend = instr_data + FD_TXN_MTU
     371           0 :   };
     372             : 
     373             :   // This should never fail.
     374           0 :   err = fd_system_program_instruction_encode( &instr, &encode_ctx );
     375           0 :   if( FD_UNLIKELY( err ) ) {
     376           0 :     return FD_EXECUTOR_INSTR_ERR_FATAL;
     377           0 :   }
     378             : 
     379             :   // Execute allocate instruction
     380           0 :   ulong instr_data_sz = (ulong)( (uchar *)encode_ctx.data - instr_data );
     381           0 :   err = fd_native_cpi_native_invoke( ctx,
     382           0 :                                      &fd_solana_system_program_id,
     383           0 :                                      instr_data,
     384           0 :                                      instr_data_sz,
     385           0 :                                      acct_metas,
     386           0 :                                      1UL,
     387           0 :                                      signers,
     388           0 :                                      signers_cnt );
     389           0 :   if( FD_UNLIKELY( err ) ) {
     390           0 :     return err;
     391           0 :   }
     392             : 
     393             :   // Prepare system program assign instruction
     394           0 :   instr = (fd_system_program_instruction_t) {
     395           0 :     .discriminant = fd_system_program_instruction_enum_assign,
     396           0 :     .inner = {
     397           0 :       .assign = fd_solana_address_lookup_table_program_id,
     398           0 :     }
     399           0 :   };
     400             : 
     401           0 :   encode_ctx = (fd_bincode_encode_ctx_t) {
     402           0 :     .data    = instr_data,
     403           0 :     .dataend = instr_data + FD_TXN_MTU
     404           0 :   };
     405             : 
     406             :   // This should never fail.
     407           0 :   err = fd_system_program_instruction_encode( &instr, &encode_ctx );
     408           0 :   if( FD_UNLIKELY( err ) ) {
     409           0 :     return FD_EXECUTOR_INSTR_ERR_FATAL;
     410           0 :   }
     411             : 
     412             :   // Execute assign instruction
     413           0 :   instr_data_sz = (ulong)( (uchar *)encode_ctx.data - instr_data );
     414           0 :   err = fd_native_cpi_native_invoke( ctx,
     415           0 :                                      &fd_solana_system_program_id,
     416           0 :                                      instr_data,
     417           0 :                                      instr_data_sz,
     418           0 :                                      acct_metas,
     419           0 :                                      1UL,
     420           0 :                                      signers,
     421           0 :                                      signers_cnt );
     422           0 :   if( FD_UNLIKELY( err ) ) {
     423           0 :     return err;
     424           0 :   }
     425             : 
     426             : 
     427             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L164-L165 */
     428           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     429             : 
     430           0 :   fd_address_lookup_table_state_t state[1];
     431           0 :   fd_address_lookup_table_state_new( state );
     432           0 :   state->discriminant = fd_address_lookup_table_state_enum_lookup_table;
     433           0 :   fd_address_lookup_table_new( &state->inner.lookup_table );
     434           0 :   fd_memcpy( state->inner.lookup_table.meta.authority.key, authority_key->key, 32UL );
     435           0 :   state->inner.lookup_table.meta.has_authority = 1;
     436           0 :   state->inner.lookup_table.meta.deactivation_slot = ULONG_MAX;
     437             : 
     438           0 :   uchar * data = NULL;
     439           0 :   ulong   dlen = 0UL;
     440           0 :   err = fd_borrowed_account_get_data_mut( &lut_acct, &data, &dlen );
     441           0 :   if( FD_UNLIKELY( err ) ) {
     442           0 :     return err;
     443           0 :   }
     444             : 
     445           0 :   int state_err = fd_addrlut_serialize_meta( state, data, sizeof(fd_address_lookup_table_state_t) );
     446           0 :   if( FD_UNLIKELY( state_err ) ) { return state_err; }
     447             : 
     448             :   /* implicit drop of lut_acct */
     449             : 
     450           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     451             : 
     452           0 : # undef ACC_IDX_LUT
     453           0 : # undef ACC_IDX_AUTHORITY
     454           0 : # undef ACC_IDX_PAYER
     455           0 : }
     456             : 
     457             : static int
     458           0 : freeze_lookup_table( fd_exec_instr_ctx_t * ctx ) {
     459             : 
     460           0 : # define ACC_IDX_LUT       (0UL)
     461           0 : # define ACC_IDX_AUTHORITY (1UL)
     462           0 :   int err;
     463             : 
     464             :   /* Prepare LUT account **********************************************/
     465             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L177-L178 */
     466             :   /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     467           0 :   fd_guarded_borrowed_account_t lut_acct = {0};
     468           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     469             : 
     470             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L178-L181 */
     471           0 :   if( FD_UNLIKELY( 0!=memcmp( fd_borrowed_account_get_owner( &lut_acct ), fd_solana_address_lookup_table_program_id.key, sizeof(fd_pubkey_t) ) ) ) {
     472           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
     473           0 :   }
     474             : 
     475             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L182 */
     476           0 :   fd_borrowed_account_drop( &lut_acct );
     477             : 
     478             :   /* Prepare authority account ****************************************/
     479             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L184-L185 */
     480           0 :   fd_pubkey_t const * authority_key = NULL;
     481             :   /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     482           0 :   fd_guarded_borrowed_account_t authority_acct = {0};
     483           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_AUTHORITY, &authority_acct );
     484             : 
     485           0 :   authority_key = authority_acct.pubkey;
     486             : 
     487             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L186-L189 */
     488           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_AUTHORITY, NULL ) ) ) {
     489           0 :     fd_log_collector_msg_literal( ctx, "Authority account must be a signer" );
     490           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     491           0 :   }
     492             : 
     493             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L191 */
     494           0 :   fd_borrowed_account_drop( &authority_acct );
     495             : 
     496             :   /* Update lookup table account **************************************/
     497             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L193-L194 */
     498           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     499             : 
     500             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L194 */
     501           0 :   uchar const * lut_data    = fd_borrowed_account_get_data( &lut_acct );
     502           0 :   ulong         lut_data_sz = fd_borrowed_account_get_data_len( &lut_acct );
     503             : 
     504             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L195 */
     505           0 :   fd_addrlut_t lut[1];
     506           0 :   err = fd_addrlut_deserialize( lut, lut_data, lut_data_sz );
     507           0 :   if( FD_UNLIKELY( err ) ) {
     508           0 :     return err;
     509           0 :   }
     510             : 
     511           0 :   fd_address_lookup_table_t * state = &lut->state.inner.lookup_table;
     512             : 
     513             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L197-L200 */
     514           0 :   if( FD_UNLIKELY( !state->meta.has_authority ) ) {
     515           0 :     fd_log_collector_msg_literal( ctx, "Lookup table is already frozen");
     516           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
     517           0 :   }
     518             : 
     519             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L201-L203 */
     520           0 :   if( FD_UNLIKELY( 0!=memcmp( state->meta.authority.key, authority_key->key, sizeof(fd_pubkey_t) ) ) ) {
     521           0 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
     522           0 :   }
     523             : 
     524             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L204-L207 */
     525           0 :   if( FD_UNLIKELY( state->meta.deactivation_slot!=ULONG_MAX ) ) {
     526           0 :     fd_log_collector_msg_literal( ctx, "Deactivated tables cannot be frozen" );
     527           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     528           0 :   }
     529             : 
     530             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L208-L211 */
     531           0 :   if( FD_UNLIKELY( !lut->addr_cnt ) ) {
     532           0 :     fd_log_collector_msg_literal( ctx, "Empty lookup tables cannot be frozen" );
     533           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     534           0 :   }
     535             : 
     536           0 :   uchar *data = NULL;
     537           0 :   ulong dlen  = 0UL;
     538           0 :   err = fd_borrowed_account_get_data_mut( &lut_acct, &data, &dlen );
     539           0 :   if( FD_UNLIKELY( err ) ) {
     540           0 :     return err;
     541           0 :   }
     542             : 
     543             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L213-L218 */
     544           0 :   state->meta.has_authority = 0;
     545             : 
     546           0 :   err = fd_addrlut_serialize_meta( &lut->state, data, dlen );
     547           0 :   if( FD_UNLIKELY( err ) ) {
     548           0 :     return err;
     549           0 :   }
     550             : 
     551             :   /* implicit drop of lut_acct */
     552             : 
     553           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     554           0 : # undef ACC_IDX_LUT
     555           0 : # undef ACC_IDX_AUTHORITY
     556           0 : }
     557             : 
     558             : static int
     559             : extend_lookup_table( fd_exec_instr_ctx_t *       ctx,
     560           0 :                      fd_addrlut_extend_t const * extend ) {
     561             : 
     562           0 : # define ACC_IDX_LUT       (0UL)
     563           0 : # define ACC_IDX_AUTHORITY (1UL)
     564           0 : # define ACC_IDX_PAYER     (2UL)
     565           0 :   int err;
     566             : 
     567             :   /* Prepare LUT account **********************************************/
     568             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L230-L236 */
     569           0 :   fd_pubkey_t const * lut_key = NULL;
     570             :   /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     571             : 
     572             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L231-L232 */
     573           0 :   fd_guarded_borrowed_account_t lut_acct = {0};
     574           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     575             : 
     576           0 :   lut_key = lut_acct.pubkey;
     577             : 
     578             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L233-235 */
     579           0 :   if( FD_UNLIKELY( 0!=memcmp( fd_borrowed_account_get_owner( &lut_acct ), fd_solana_address_lookup_table_program_id.key, sizeof(fd_pubkey_t) ) ) )
     580           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
     581             : 
     582             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L237 */
     583           0 :   fd_borrowed_account_drop( &lut_acct );
     584             : 
     585             :   /* Prepare authority account ****************************************/
     586             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L238-L245 */
     587           0 :   fd_pubkey_t const * authority_key = NULL;
     588             :   /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     589             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L239-L240 */
     590           0 :   fd_guarded_borrowed_account_t authority_acct = {0};
     591           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_AUTHORITY, &authority_acct );
     592             : 
     593           0 :   authority_key = authority_acct.pubkey;
     594             : 
     595             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L241-L244 */
     596           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_AUTHORITY, NULL ) ) ) {
     597           0 :     fd_log_collector_msg_literal( ctx, "Authority account must be a signer" );
     598           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     599           0 :   }
     600             : 
     601             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L246 */
     602           0 :   fd_borrowed_account_drop( &authority_acct );
     603             : 
     604           0 :   uchar const * lut_data          = NULL;
     605           0 :   ulong         lut_data_sz       = 0UL;
     606           0 :   ulong         lut_lamports      = 0UL;
     607           0 :   ulong         new_table_data_sz = 0UL;
     608             : 
     609             :   /* Update lookup table account **************************************/
     610             : 
     611             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L248-L249 */
     612           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     613             : 
     614           0 :   lut_data     = fd_borrowed_account_get_data( &lut_acct );
     615           0 :   lut_data_sz  = fd_borrowed_account_get_data_len( &lut_acct );
     616           0 :   lut_lamports = fd_borrowed_account_get_lamports( &lut_acct );
     617             : 
     618             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L251 */
     619           0 :   fd_addrlut_t lut[1];
     620           0 :   err = fd_addrlut_deserialize( lut, (uchar *)lut_data, lut_data_sz );
     621           0 :   if( FD_UNLIKELY( err ) ) {
     622           0 :     return err;
     623           0 :   }
     624             : 
     625           0 :   fd_address_lookup_table_t * state = &lut->state.inner.lookup_table;
     626             : 
     627             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L253-L255 */
     628           0 :   if( FD_UNLIKELY( !state->meta.has_authority ) ) {
     629           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
     630           0 :   }
     631             : 
     632             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L256-L258 */
     633           0 :   if( FD_UNLIKELY( 0!=memcmp( state->meta.authority.key, authority_key->key, sizeof(fd_pubkey_t) ) ) ) {
     634           0 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
     635           0 :   }
     636             : 
     637             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L259-L262 */
     638           0 :   if( FD_UNLIKELY( state->meta.deactivation_slot != ULONG_MAX ) ) {
     639           0 :     fd_log_collector_msg_literal( ctx, "Deactivated tables cannot be extended" );
     640           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     641           0 :   }
     642             : 
     643             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L263-L269 */
     644           0 :   if( FD_UNLIKELY( lut->addr_cnt >= FD_ADDRLUT_MAX_ADDR_CNT ) ) {
     645           0 :     fd_log_collector_msg_literal( ctx, "Lookup table is full and cannot contain more addresses" );
     646           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     647           0 :   }
     648             : 
     649             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L271-L274 */
     650           0 :   if( FD_UNLIKELY( !extend->new_addrs_len ) ) {
     651           0 :     fd_log_collector_msg_literal( ctx, "Must extend with at least one address" );
     652           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     653           0 :   }
     654             : 
     655             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L276-L279 */
     656           0 :   ulong old_addr_cnt = lut->addr_cnt;
     657           0 :   ulong new_addr_cnt = lut->addr_cnt + extend->new_addrs_len;
     658           0 :   if( FD_UNLIKELY( new_addr_cnt > FD_ADDRLUT_MAX_ADDR_CNT ) ) {
     659             :     /* Max msg_sz: 65 - 6 + 20*2 = 99 < 127 => we can use printf */
     660           0 :     fd_log_collector_printf_dangerous_max_127( ctx,
     661           0 :       "Extended lookup table length %lu would exceed max capacity of %lu", new_addr_cnt, FD_ADDRLUT_MAX_ADDR_CNT );
     662           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     663           0 :   }
     664             : 
     665             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L290 */
     666           0 :   fd_sol_sysvar_clock_t clock_;
     667           0 :   fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
     668           0 :   if( FD_UNLIKELY( !clock ) ) {
     669           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     670           0 :   }
     671             : 
     672             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L291-L299 */
     673           0 :   if( clock->slot!=state->meta.last_extended_slot ) {
     674           0 :     state->meta.last_extended_slot             = clock->slot;
     675           0 :     state->meta.last_extended_slot_start_index = (uchar)lut->addr_cnt;
     676           0 :   }
     677             : 
     678             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/address-lookup-table/src/processor.rs#L302
     679           0 :   new_table_data_sz = FD_ADDRLUT_META_SZ + new_addr_cnt * sizeof(fd_pubkey_t);
     680             : 
     681             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/address-lookup-table/src/processor.rs#L286 */
     682           0 :   uchar * lut_data_mut = NULL;
     683           0 :   ulong   lut_data_mut_len = 0;
     684           0 :   err = fd_borrowed_account_get_data_mut( &lut_acct, &lut_data_mut, &lut_data_mut_len );
     685           0 :   if( FD_UNLIKELY( err ) ) {
     686           0 :     return err;
     687           0 :   }
     688           0 :   fd_account_meta_resize( lut_acct.meta, new_table_data_sz );
     689             : 
     690             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L307-L310 */
     691           0 :   err = fd_addrlut_serialize_meta( &lut->state, lut_data_mut, lut_data_mut_len );
     692           0 :   if( FD_UNLIKELY( err ) ) {
     693           0 :     return err;
     694           0 :   }
     695             : 
     696             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L311-L313 */
     697           0 :   do {
     698           0 :     uchar * new_keys = lut_data_mut + FD_ADDRLUT_META_SZ + old_addr_cnt * sizeof(fd_pubkey_t);
     699           0 :     fd_memcpy( new_keys, extend->new_addrs, extend->new_addrs_len * sizeof(fd_pubkey_t) );
     700           0 :   } while(0);
     701           0 :   fd_borrowed_account_set_data_length( &lut_acct, new_table_data_sz );
     702           0 :   lut->addr            = (fd_pubkey_t *)(lut_data_mut + FD_ADDRLUT_META_SZ);
     703           0 :   lut->addr_cnt        = new_addr_cnt;
     704             : 
     705             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L316 */
     706           0 :   fd_borrowed_account_drop( &lut_acct );
     707             : 
     708             : 
     709             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L317-L321 */
     710           0 :   fd_rent_t rent[1] = { fd_sysvar_cache_rent_read_nofail( ctx->sysvar_cache ) };
     711           0 :   ulong required_lamports = fd_rent_exempt_minimum_balance( rent, new_table_data_sz );
     712           0 :   /* */ required_lamports = fd_ulong_max    ( required_lamports, 1UL );
     713           0 :   /* */ required_lamports = fd_ulong_sat_sub( required_lamports, lut_lamports );
     714             : 
     715           0 :   if( required_lamports ) {
     716           0 :     fd_pubkey_t const * payer_key = NULL;
     717             : 
     718             :     /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     719             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L325-L326 */
     720           0 :     fd_guarded_borrowed_account_t payer_acct = {0};
     721           0 :     FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_PAYER, &payer_acct );
     722             : 
     723           0 :     payer_key = payer_acct.pubkey;
     724             :     /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L327-L330 */
     725           0 :     if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_PAYER, NULL ) ) ) {
     726           0 :       fd_log_collector_msg_literal( ctx, "Payer account must be a signer" );
     727           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     728           0 :     }
     729             : 
     730             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L332 */
     731           0 :     fd_borrowed_account_drop( &payer_acct );
     732             : 
     733             :     // Create account metas
     734           0 :     fd_vm_rust_account_meta_t acct_metas[ 2UL ];
     735           0 :     fd_native_cpi_create_account_meta( payer_key, 1, 1, &acct_metas[0] );
     736           0 :     fd_native_cpi_create_account_meta( lut_key,   0, 1, &acct_metas[1] );
     737             : 
     738             :     // Create signers list
     739           0 :     fd_pubkey_t signers[16];
     740           0 :     ulong signers_cnt = 1UL;
     741           0 :     signers[0]        = *payer_key;
     742             : 
     743             :     // Create system program instruction
     744           0 :     uchar instr_data[FD_TXN_MTU];
     745           0 :     fd_system_program_instruction_t instr = {
     746           0 :       .discriminant = fd_system_program_instruction_enum_transfer,
     747           0 :       .inner = {
     748           0 :         .transfer = required_lamports,
     749           0 :       }
     750           0 :     };
     751             : 
     752           0 :     fd_bincode_encode_ctx_t encode_ctx = {
     753           0 :       .data    = instr_data,
     754           0 :       .dataend = instr_data + FD_TXN_MTU
     755           0 :     };
     756             : 
     757             :     // This should never fail.
     758           0 :     int err = fd_system_program_instruction_encode( &instr, &encode_ctx );
     759           0 :     if( FD_UNLIKELY( err ) ) {
     760           0 :       return FD_EXECUTOR_INSTR_ERR_FATAL;
     761           0 :     }
     762             : 
     763           0 :     ulong instr_data_sz = (ulong)( (uchar *)encode_ctx.data - instr_data );
     764           0 :     err = fd_native_cpi_native_invoke( ctx,
     765           0 :                                        &fd_solana_system_program_id,
     766           0 :                                        instr_data,
     767           0 :                                        instr_data_sz,
     768           0 :                                        acct_metas,
     769           0 :                                        2UL,
     770           0 :                                        signers,
     771           0 :                                        signers_cnt );
     772           0 :     if( FD_UNLIKELY( err ) ) {
     773           0 :       return err;
     774           0 :     }
     775           0 :   }
     776             : 
     777           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     778             : 
     779           0 : # undef ACC_IDX_LUT
     780           0 : # undef ACC_IDX_AUTHORITY
     781           0 : # undef ACC_IDX_PAYER
     782           0 : }
     783             : 
     784             : static int
     785           0 : deactivate_lookup_table( fd_exec_instr_ctx_t * ctx ) {
     786             : 
     787           0 : # define ACC_IDX_LUT       (0UL)
     788           0 : # define ACC_IDX_AUTHORITY (1UL)
     789           0 :   int err;
     790             : 
     791             :   /* Prepare LUT account **********************************************/
     792             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L346-L351 */
     793             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
     794             : 
     795             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L347-L348 */
     796           0 :   fd_guarded_borrowed_account_t lut_acct = {0};
     797           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     798             : 
     799             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L348-L350 */
     800           0 :   if( FD_UNLIKELY( 0!=memcmp( fd_borrowed_account_get_owner( &lut_acct ), fd_solana_address_lookup_table_program_id.key, sizeof(fd_pubkey_t) ) ) )
     801           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
     802             : 
     803             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L352 */
     804           0 :   fd_borrowed_account_drop( &lut_acct );
     805             : 
     806             :   /* Prepare authority account ****************************************/
     807             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L353-L360 */
     808           0 :   fd_pubkey_t const * authority_key = NULL;
     809             :   /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     810             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L354-L355 */
     811           0 :   fd_guarded_borrowed_account_t authority_acct = {0};
     812           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_AUTHORITY, &authority_acct );
     813             : 
     814           0 :   authority_key = authority_acct.pubkey;
     815             : 
     816             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L356-L359 */
     817           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_AUTHORITY, NULL ) ) ) {
     818           0 :     fd_log_collector_msg_literal( ctx, "Authority account must be a signer" );
     819           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     820           0 :   }
     821             : 
     822             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L361 */
     823           0 :   fd_borrowed_account_drop( &authority_acct );
     824             : 
     825             :   /* Update lookup table account **************************************/
     826             : 
     827             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L363-L364 */
     828           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     829             : 
     830             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L364 */
     831           0 :   uchar const * lut_data    = fd_borrowed_account_get_data( &lut_acct );
     832           0 :   ulong         lut_data_sz = fd_borrowed_account_get_data_len( &lut_acct );
     833             : 
     834             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L365 */
     835           0 :   fd_addrlut_t lut[1];
     836           0 :   err = fd_addrlut_deserialize( lut, (uchar *)lut_data, lut_data_sz );
     837           0 :   if( FD_UNLIKELY( err ) ) {
     838           0 :     return err;
     839           0 :   }
     840             : 
     841           0 :   fd_address_lookup_table_t * state = &lut->state.inner.lookup_table;
     842             : 
     843             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L367-L370 */
     844           0 :   if( FD_UNLIKELY( !state->meta.has_authority ) ) {
     845           0 :     fd_log_collector_msg_literal( ctx, "Lookup table is frozen" );
     846           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
     847           0 :   }
     848             : 
     849             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L371-L373 */
     850           0 :   if( FD_UNLIKELY( 0!=memcmp( state->meta.authority.key, authority_key->key, sizeof(fd_pubkey_t) ) ) ) {
     851           0 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
     852           0 :   }
     853             : 
     854             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L374-L377 */
     855           0 :   if( FD_UNLIKELY( state->meta.deactivation_slot != ULONG_MAX ) ) {
     856           0 :     fd_log_collector_msg_literal( ctx, "Lookup table is already deactivated" );
     857           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     858           0 :   }
     859             : 
     860             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L380 */
     861           0 :   fd_sol_sysvar_clock_t clock_;
     862           0 :   fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
     863           0 :   if( FD_UNLIKELY( !clock ) ) {
     864           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     865           0 :   }
     866             : 
     867           0 :   uchar * data = NULL;
     868           0 :   ulong   dlen = 0UL;
     869           0 :   err = fd_borrowed_account_get_data_mut ( &lut_acct, &data, &dlen );
     870           0 :   if( FD_UNLIKELY( err ) ) {
     871           0 :     return err;
     872           0 :   }
     873             : 
     874             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L381 */
     875           0 :   state->meta.deactivation_slot = clock->slot;
     876             : 
     877             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L383-L386 */
     878           0 :   err = fd_addrlut_serialize_meta( &lut->state, data, dlen );
     879           0 :   if( FD_UNLIKELY( err ) ) {
     880           0 :     return err;
     881           0 :   }
     882             : 
     883             :   /* implicit drop of lut_acct */
     884             : 
     885           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     886             : 
     887           0 : # undef ACC_IDX_LUT
     888           0 : # undef ACC_IDX_AUTHORITY
     889           0 : }
     890             : 
     891             : static int
     892           0 : close_lookup_table( fd_exec_instr_ctx_t * ctx ) {
     893             : 
     894           0 : # define ACC_IDX_LUT       (0UL)
     895           0 : # define ACC_IDX_AUTHORITY (1UL)
     896           0 : # define ACC_IDX_RECIPIENT (2UL)
     897           0 :   int err;
     898             : 
     899             :   /* Prepare LUT account **********************************************/
     900             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L395-L400 */
     901             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
     902             : 
     903             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L396-L397 */
     904           0 :   fd_guarded_borrowed_account_t lut_acct = {0};
     905           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     906             : 
     907             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L397-L399 */
     908           0 :   if( FD_UNLIKELY( 0!=memcmp( fd_borrowed_account_get_owner( &lut_acct ), fd_solana_address_lookup_table_program_id.key, sizeof(fd_pubkey_t) ) ) )
     909           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
     910             : 
     911             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L401 */
     912           0 :   fd_borrowed_account_drop( &lut_acct );
     913             : 
     914             :   /* Prepare authority account ****************************************/
     915             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L402-L409 */
     916           0 :   fd_pubkey_t const * authority_key = NULL;
     917             :   /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     918             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L403-L404 */
     919           0 :   fd_guarded_borrowed_account_t authority_acct = {0};
     920           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_AUTHORITY, &authority_acct );
     921             : 
     922           0 :   authority_key = authority_acct.pubkey;
     923             : 
     924             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L405-L408 */
     925           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_AUTHORITY, NULL ) ) ) {
     926           0 :     fd_log_collector_msg_literal( ctx, "Authority account must be a signer" );
     927           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     928           0 :   }
     929             : 
     930             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L410 */
     931           0 :   fd_borrowed_account_drop( &authority_acct );
     932             : 
     933             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L411 */
     934           0 :   err = fd_exec_instr_ctx_check_num_insn_accounts( ctx, 3 );
     935           0 :   if( FD_UNLIKELY( err ) ) {
     936           0 :     return err;
     937           0 :   }
     938             : 
     939             :   /* It's ok to directly access the instruction accounts because we already verified 3 expected instruction accounts.
     940             :      https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L412-L420 */
     941           0 :   if( FD_UNLIKELY( ctx->instr->accounts[0].index_in_transaction ==
     942           0 :                    ctx->instr->accounts[2].index_in_transaction ) ) {
     943           0 :     fd_log_collector_msg_literal( ctx, "Lookup table cannot be the recipient of reclaimed lamports" );
     944           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     945           0 :   }
     946             : 
     947           0 :   ulong         withdrawn_lamports = 0UL;
     948           0 :   uchar const * lut_data           = NULL;
     949           0 :   ulong         lut_data_sz        = 0UL;
     950             : 
     951             :   /* Update lookup table account **************************************/
     952             : 
     953             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L423-L424 */
     954           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     955             : 
     956           0 :   withdrawn_lamports = fd_borrowed_account_get_lamports( &lut_acct );
     957           0 :   lut_data           = fd_borrowed_account_get_data( &lut_acct );
     958           0 :   lut_data_sz        = fd_borrowed_account_get_data_len( &lut_acct );
     959             : 
     960             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L426 */
     961           0 :   fd_addrlut_t lut[1];
     962           0 :   err = fd_addrlut_deserialize( lut, (uchar *)lut_data, lut_data_sz );
     963           0 :   if( FD_UNLIKELY( err ) ) {
     964           0 :     return err;
     965           0 :   }
     966             : 
     967           0 :   fd_address_lookup_table_t * state = &lut->state.inner.lookup_table;
     968             : 
     969             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L428-L431 */
     970           0 :   if( FD_UNLIKELY( !state->meta.has_authority ) ) {
     971           0 :     fd_log_collector_msg_literal( ctx,  "Lookup table is frozen" );
     972           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
     973           0 :   }
     974             : 
     975             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L432-L434 */
     976           0 :   if( FD_UNLIKELY( 0!=memcmp( state->meta.authority.key, authority_key->key, sizeof(fd_pubkey_t) ) ) ) {
     977           0 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
     978           0 :   }
     979             : 
     980             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L437 */
     981           0 :   fd_sol_sysvar_clock_t clock_;
     982           0 :   fd_sol_sysvar_clock_t * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
     983           0 :   if( FD_UNLIKELY( !clock ) ) {
     984           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     985           0 :   }
     986             : 
     987             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L438 */
     988           0 :   fd_slot_hash_t const * slot_hash = fd_sysvar_cache_slot_hashes_join_const( ctx->sysvar_cache );
     989           0 :   if( FD_UNLIKELY( !slot_hash ) ) {
     990           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     991           0 :   }
     992             : 
     993             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L440 */
     994           0 :   ulong remaining_blocks = 0UL;
     995           0 :   int status = fd_addrlut_status( &state->meta, clock->slot, slot_hash, &remaining_blocks );
     996           0 :   fd_sysvar_cache_slot_hashes_leave_const( ctx->sysvar_cache, slot_hash );
     997             : 
     998           0 :   switch( status ) {
     999           0 :     case FD_ADDRLUT_STATUS_ACTIVATED:
    1000           0 :       fd_log_collector_msg_literal( ctx, "Lookup table is not deactivated" );
    1001           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1002           0 :     case FD_ADDRLUT_STATUS_DEACTIVATING:
    1003             :       /* Max msg_sz: 65 - 3 + 20 = 82 < 127 => we can use printf */
    1004           0 :       fd_log_collector_printf_dangerous_max_127( ctx,
    1005           0 :         "Table cannot be closed until it's fully deactivated in %lu blocks", remaining_blocks );
    1006           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1007           0 :     case FD_ADDRLUT_STATUS_DEACTIVATED:
    1008           0 :       break;
    1009           0 :     default:
    1010           0 :       __builtin_unreachable();
    1011           0 :   }
    1012             : 
    1013             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L456 */
    1014           0 :   fd_borrowed_account_drop( &lut_acct );
    1015             : 
    1016             :   /* Add lamports to recipient ****************************************/
    1017             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
    1018             : 
    1019             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L458-L459 */
    1020           0 :   fd_guarded_borrowed_account_t recipient_acct = {0};
    1021           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_RECIPIENT, &recipient_acct );
    1022             : 
    1023           0 :   err = fd_borrowed_account_checked_add_lamports( &recipient_acct, withdrawn_lamports );
    1024           0 :   if( FD_UNLIKELY( err ) ) {
    1025           0 :     return err;
    1026           0 :   }
    1027             : 
    1028             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L461 */
    1029           0 :   fd_borrowed_account_drop( &recipient_acct );
    1030             : 
    1031             :   /* Delete LUT account ***********************************************/
    1032             : 
    1033             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L463-L464 */
    1034           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
    1035             : 
    1036           0 :   err = fd_borrowed_account_set_data_length( &lut_acct, 0UL );
    1037           0 :   if( FD_UNLIKELY( err ) ) {
    1038           0 :     return err;
    1039           0 :   }
    1040             : 
    1041           0 :   err = fd_borrowed_account_set_lamports( &lut_acct, 0UL );
    1042           0 :   if( FD_UNLIKELY( err ) ) {
    1043           0 :     return err;
    1044           0 :   }
    1045             : 
    1046           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1047             : 
    1048           0 : # undef ACC_IDX_LUT
    1049           0 : # undef ACC_IDX_AUTHORITY
    1050           0 : # undef ACC_IDX_RECIPIENT
    1051           0 : }
    1052             : 
    1053             : int
    1054           0 : fd_address_lookup_table_program_execute( fd_exec_instr_ctx_t * ctx ) {
    1055             :   /* Prevent execution of migrated native programs */
    1056           0 :   if( FD_UNLIKELY( FD_FEATURE_ACTIVE_BANK( ctx->bank, migrate_address_lookup_table_program_to_core_bpf ) ) ) {
    1057           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    1058           0 :   }
    1059             : 
    1060           0 :   FD_EXEC_CU_UPDATE( ctx, DEFAULT_COMPUTE_UNITS );
    1061             : 
    1062           0 :   uchar const * instr_data    = ctx->instr->data;
    1063           0 :   ulong         instr_data_sz = ctx->instr->data_sz;
    1064           0 :   if( FD_UNLIKELY( instr_data==NULL ) ) {
    1065           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1066           0 :   }
    1067           0 :   if( FD_UNLIKELY( instr_data_sz>FD_TXN_MTU ) ) {
    1068           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1069           0 :   }
    1070             : 
    1071             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L28 */
    1072           0 :   uchar instr_mem[ FD_ADDRLUT_INSTR_FOOTPRINT ] __attribute__((aligned(alignof(fd_addrlut_instruction_t))));
    1073           0 :   fd_addrlut_instruction_t * instr = fd_bincode_decode_static(
    1074           0 :       addrlut_instruction,
    1075           0 :       instr_mem,
    1076           0 :       instr_data,
    1077           0 :       instr_data_sz,
    1078           0 :       NULL );
    1079           0 :   if( FD_UNLIKELY( !instr ) ) {
    1080           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1081           0 :   }
    1082             : 
    1083           0 :   switch( instr->discriminant ) {
    1084           0 :   case fd_addrlut_instruction_enum_create_lut:
    1085           0 :     return create_lookup_table( ctx, &instr->inner.create_lut );
    1086           0 :   case fd_addrlut_instruction_enum_freeze_lut:
    1087           0 :     return freeze_lookup_table( ctx );
    1088           0 :   case fd_addrlut_instruction_enum_extend_lut:
    1089           0 :     return extend_lookup_table( ctx, &instr->inner.extend_lut );
    1090           0 :   case fd_addrlut_instruction_enum_deactivate_lut:
    1091           0 :     return deactivate_lookup_table( ctx );
    1092           0 :   case fd_addrlut_instruction_enum_close_lut:
    1093           0 :     return close_lookup_table( ctx );
    1094           0 :   default:
    1095           0 :     break;
    1096           0 :   }
    1097             : 
    1098           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1099           0 : }
    1100             : 
    1101             : /**********************************************************************/
    1102             : /* Public API                                                         */
    1103             : /**********************************************************************/
    1104             : 
    1105             : /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L72-L78 */
    1106             : static uchar
    1107             : is_active( fd_address_lookup_table_t const * self,
    1108             :            ulong                             current_slot,
    1109           0 :            fd_slot_hash_t const *            slot_hashes ) { /* deque */
    1110             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L73-L77 */
    1111           0 :   ulong _dummy[1];
    1112           0 :   switch( fd_addrlut_status( &self->meta, current_slot, slot_hashes, _dummy ) ) {
    1113           0 :     case FD_ADDRLUT_STATUS_ACTIVATED:
    1114           0 :     case FD_ADDRLUT_STATUS_DEACTIVATING:
    1115           0 :       return 1;
    1116           0 :     case FD_ADDRLUT_STATUS_DEACTIVATED:
    1117           0 :       return 0;
    1118           0 :     default:
    1119           0 :       __builtin_unreachable();
    1120           0 :   }
    1121           0 : }
    1122             : 
    1123             : /* Sets active_addresses_len on success
    1124             :    https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L142-L164 */
    1125             : int
    1126             : fd_get_active_addresses_len( fd_address_lookup_table_t * self,
    1127             :                              ulong                       current_slot,
    1128             :                              fd_slot_hash_t const *      slot_hashes, /* deque */
    1129             :                              ulong                       addresses_len,
    1130           0 :                              ulong *                     active_addresses_len ) {
    1131             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L147-L152 */
    1132           0 :   if( FD_UNLIKELY( !is_active( self, current_slot, slot_hashes ) ) ) {
    1133           0 :     return FD_RUNTIME_TXN_ERR_ADDRESS_LOOKUP_TABLE_NOT_FOUND;
    1134           0 :   }
    1135             : 
    1136             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L157-L161 */
    1137           0 :   *active_addresses_len = ( current_slot > self->meta.last_extended_slot )
    1138           0 :       ? addresses_len
    1139           0 :       : self->meta.last_extended_slot_start_index;
    1140             : 
    1141           0 :   return FD_RUNTIME_EXECUTE_SUCCESS;
    1142           0 : }

Generated by: LCOV version 1.14