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: 19 687 2.8 %
Date: 2025-10-27 04:40:00 Functions: 3 13 23.1 %

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

Generated by: LCOV version 1.14