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 648 0.0 %
Date: 2025-03-20 12:08:36 Functions: 0 13 0.0 %

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

Generated by: LCOV version 1.14