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 681 0.0 %
Date: 2025-06-30 04:56:04 Functions: 0 13 0.0 %

          Line data    Source code
       1             : #include "fd_address_lookup_table_program.h"
       2             : #include "../fd_executor.h"
       3             : #include "../fd_pubkey_utils.h"
       4             : #include "../fd_borrowed_account.h"
       5             : #include "../sysvar/fd_sysvar_slot_hashes.h"
       6             : #include "../sysvar/fd_sysvar_clock.h"
       7             : #include "../../vm/syscall/fd_vm_syscall.h"
       8             : #include "fd_native_cpi.h"
       9             : 
      10             : #include <string.h>
      11             : 
      12             : struct fd_addrlut {
      13             :   fd_address_lookup_table_state_t state;
      14             : 
      15             :   fd_pubkey_t const * addr;  /* points into account data */
      16             :   ulong               addr_cnt;
      17             : };
      18             : 
      19             : typedef struct fd_addrlut fd_addrlut_t;
      20             : 
      21           0 : #define FD_ADDRLUT_META_SZ       (56UL)
      22           0 : #define FD_ADDRLUT_MAX_ADDR_CNT (256UL)
      23             : #define DEFAULT_COMPUTE_UNITS   (750UL)
      24           0 : #define MAX_ENTRIES             FD_SYSVAR_SLOT_HASHES_CAP
      25             : 
      26             : static fd_addrlut_t *
      27           0 : fd_addrlut_new( void * mem ) {
      28             : 
      29           0 :   if( FD_UNLIKELY( !mem ) ) {
      30           0 :     FD_LOG_WARNING(( "NULL mem" ));
      31           0 :     return NULL;
      32           0 :   }
      33             : 
      34           0 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_addrlut_t) ) ) ) {
      35           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      36           0 :     return NULL;
      37           0 :   }
      38             : 
      39           0 :   return fd_type_pun( mem );
      40           0 : }
      41             : 
      42             : static int
      43             : fd_addrlut_deserialize( fd_addrlut_t * lut,
      44             :                         uchar const *  data,
      45           0 :                         ulong          data_sz ) {
      46             : 
      47           0 :   lut = fd_addrlut_new( lut ); FD_TEST( lut );
      48             : 
      49             :   /* We anticipate that we require no allocations to decode the address lookup
      50             :      table state size and that the data is already preallocated. */
      51           0 :   fd_bincode_decode_ctx_t decode = {
      52           0 :     .data    = data,
      53           0 :     .dataend = data+data_sz
      54           0 :   };
      55             : 
      56           0 :   ulong total_sz = 0UL;
      57           0 :   if( FD_UNLIKELY( fd_address_lookup_table_state_decode_footprint( &decode, &total_sz )!=FD_BINCODE_SUCCESS ) ) {
      58           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      59           0 :   }
      60             : 
      61             :   /* NOTE: We technically don't need this check if we assume that the caller
      62             :      is correctly handling the memory that is passed into this function. */
      63           0 :   if( FD_UNLIKELY( total_sz!=sizeof(fd_address_lookup_table_state_t) ) ) {
      64           0 :     FD_LOG_ERR(( "Unexpected total size of address lookup table state" ));
      65           0 :   }
      66             : 
      67           0 :   fd_address_lookup_table_state_decode( &lut->state, &decode );
      68             : 
      69           0 :   if( lut->state.discriminant==fd_address_lookup_table_state_enum_uninitialized )
      70           0 :     return FD_EXECUTOR_INSTR_ERR_UNINITIALIZED_ACCOUNT;
      71           0 :   FD_TEST( lut->state.discriminant == fd_address_lookup_table_state_enum_lookup_table );
      72             : 
      73           0 :   if( data_sz < FD_ADDRLUT_META_SZ )
      74           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      75             : 
      76           0 :   uchar const * raw_addr_data    = data   +FD_ADDRLUT_META_SZ;
      77           0 :   ulong         raw_addr_data_sz = data_sz-FD_ADDRLUT_META_SZ;
      78             : 
      79           0 :   if( !fd_ulong_is_aligned( raw_addr_data_sz, 32UL ) )
      80           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      81             : 
      82           0 :   lut->addr     = fd_type_pun_const( raw_addr_data );
      83           0 :   lut->addr_cnt = raw_addr_data_sz / 32UL;
      84             : 
      85           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
      86           0 : }
      87             : 
      88             : static int
      89             : fd_addrlut_serialize_meta( fd_address_lookup_table_state_t const * state,
      90             :                            uchar * data,
      91           0 :                            ulong   data_sz ) {
      92             : 
      93             :   /* TODO can this ever get hit?  All code paths to this function seem
      94             :      to check account data size during deserialization. */
      95           0 :   if( FD_UNLIKELY( data_sz<FD_ADDRLUT_META_SZ ) )
      96           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      97             : 
      98           0 :   fd_bincode_encode_ctx_t encode =
      99           0 :     { .data    = data,
     100           0 :       .dataend = data+FD_ADDRLUT_META_SZ };
     101           0 :   fd_memset( data, 0, (ulong)encode.dataend - (ulong)encode.data );
     102             : 
     103           0 :   int bin_err = fd_address_lookup_table_state_encode( state, &encode );
     104           0 :   FD_TEST( !bin_err );
     105             : 
     106           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     107           0 : }
     108             : 
     109             : static ulong
     110           0 : slot_hashes_position( fd_slot_hash_t const * hashes, ulong slot ) {
     111             :   /* Logic is copied from slice::binary_search_by() in Rust. While not fully optimized,
     112             :      it aims to achieve fuzzing conformance for both sorted and unsorted inputs.
     113             :      Returns the slot hash position of the input slot. */
     114           0 :   ulong size = deq_fd_slot_hash_t_cnt( hashes );
     115           0 :   if( FD_UNLIKELY( size==0UL ) ) return ULONG_MAX;
     116             : 
     117           0 :   ulong base = 0UL;
     118           0 :   while( size>1UL ) {
     119           0 :     ulong half = size / 2UL;
     120           0 :     ulong mid = base + half;
     121           0 :     ulong mid_slot = deq_fd_slot_hash_t_peek_index_const( hashes, mid )->slot;
     122           0 :     base = (slot>mid_slot) ? base : mid;
     123           0 :     size -= half;
     124           0 :   }
     125             : 
     126           0 :   return deq_fd_slot_hash_t_peek_index_const( hashes, base )->slot==slot ? base : ULONG_MAX;
     127           0 : }
     128             : 
     129             : /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L81-L104 */
     130             : static uchar
     131             : fd_addrlut_status( fd_lookup_table_meta_t const * state,
     132             :                    ulong                          current_slot,
     133             :                    fd_slot_hash_t const *         slot_hashes,
     134           0 :                    ulong *                        remaining_blocks ) {
     135             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L82-L83 */
     136           0 :   if( state->deactivation_slot==ULONG_MAX ) {
     137           0 :     return FD_ADDRLUT_STATUS_ACTIVATED;
     138           0 :   }
     139             : 
     140             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L84-L87 */
     141           0 :   if( state->deactivation_slot==current_slot ) {
     142           0 :     *remaining_blocks = MAX_ENTRIES + 1UL;
     143           0 :     return FD_ADDRLUT_STATUS_DEACTIVATING;
     144           0 :   }
     145             : 
     146             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L88-L100 */
     147           0 :   ulong slot_hash_position = slot_hashes_position( slot_hashes, state->deactivation_slot );
     148           0 :   if( slot_hash_position!=ULONG_MAX ) {
     149           0 :     *remaining_blocks = MAX_ENTRIES - slot_hash_position;
     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#L102 */
     154           0 :   return FD_ADDRLUT_STATUS_DEACTIVATED;
     155           0 : }
     156             : 
     157             : /* Note on uses of fd_borrowed_account_acquire_write_is_safe:
     158             : 
     159             :    In some places of this program, the Agave implementation acquires a
     160             :    "mutable borrow" on the account that is immediately dropped before
     161             :    any borrow can occur.  In other words, this borrow attempt only
     162             :    introduces a "borrow failed" error case into the protocol but
     163             :    otherwise introduces no side effects.  i.e.
     164             : 
     165             :      if not fd_borrowed_account_acquire_write():
     166             :        return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED
     167             :      ... read only operations ...
     168             :      fd_borrowed_account_release_write()
     169             :      ... arbitrary logic ...
     170             : 
     171             :    Is equivalent to
     172             : 
     173             :      if not fd_borrowed_account_acquire_write_is_safe():
     174             :        return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED
     175             :      ... read only operations ...
     176             :      ... arbitrary logic ... */
     177             : 
     178             : static int
     179             : create_lookup_table( fd_exec_instr_ctx_t *       ctx,
     180           0 :                      fd_addrlut_create_t const * create ) {
     181             : 
     182           0 : # define ACC_IDX_LUT       (0UL)
     183           0 : # define ACC_IDX_AUTHORITY (1UL)
     184           0 : # define ACC_IDX_PAYER     (2UL)
     185             : 
     186           0 :   int err;
     187             : 
     188           0 :   ulong               lut_lamports  = 0UL;
     189           0 :   fd_pubkey_t const * lut_key       = NULL;
     190           0 :   fd_pubkey_t const * lut_owner     = NULL;
     191           0 :   fd_pubkey_t const * authority_key = NULL;
     192           0 :   fd_pubkey_t const * payer_key     = NULL;
     193             : 
     194             :   /* Prepare LUT account **********************************************/
     195             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L59-L60 */
     196             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
     197           0 :   fd_guarded_borrowed_account_t lut_acct;
     198           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     199             : 
     200             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L60-L62 */
     201           0 :   lut_lamports = fd_borrowed_account_get_lamports( &lut_acct );
     202           0 :   lut_key      = lut_acct.acct->pubkey;
     203           0 :   lut_owner    = fd_borrowed_account_get_owner( &lut_acct );
     204             : 
     205             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L63-L70 */
     206           0 :   if( !FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, relax_authority_signer_check_for_lookup_table_creation )
     207           0 :       && fd_borrowed_account_get_data_len( &lut_acct ) != 0UL ) {
     208           0 :     fd_log_collector_msg_literal( ctx, "Table account must not be allocated" );
     209           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED;
     210           0 :   }
     211             : 
     212             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L72 */
     213           0 :   fd_borrowed_account_drop( &lut_acct );
     214             : 
     215             :   /* Prepare authority account ****************************************/
     216             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L74-L75 */
     217             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
     218           0 :   fd_guarded_borrowed_account_t authority_acct;
     219           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_AUTHORITY, &authority_acct );
     220             : 
     221             : 
     222             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L75 */
     223           0 :   authority_key = authority_acct.acct->pubkey;
     224             : 
     225             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L76-L83 */
     226           0 :   if( !FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, relax_authority_signer_check_for_lookup_table_creation )
     227           0 :       && !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_AUTHORITY ) ) {
     228           0 :     fd_log_collector_msg_literal( ctx, "Authority account must be a signer" );
     229           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     230           0 :   }
     231             : 
     232             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L85 */
     233           0 :   fd_borrowed_account_drop( &authority_acct );
     234             : 
     235             :   /* Prepare payer account ********************************************/
     236             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L87-L88 */
     237             :     /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     238           0 :   fd_guarded_borrowed_account_t payer_acct;
     239           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_PAYER, &payer_acct );
     240             : 
     241           0 :   payer_key = payer_acct.acct->pubkey;
     242             : 
     243             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L89-L92 */
     244           0 :   if( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_PAYER ) ) {
     245           0 :     fd_log_collector_msg_literal( ctx, "Payer account must be a signer" );
     246           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     247           0 :   }
     248             : 
     249             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L94 */
     250           0 :   fd_borrowed_account_drop( &payer_acct );
     251             : 
     252           0 :   ulong derivation_slot = 1UL;
     253             : 
     254           0 :   do {
     255           0 :     fd_slot_hashes_global_t const * slot_hashes_global = fd_sysvar_slot_hashes_read( ctx->txn_ctx->funk, ctx->txn_ctx->funk_txn, ctx->txn_ctx->spad );
     256             : 
     257           0 :     if( FD_UNLIKELY( !slot_hashes_global ) ) {
     258           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     259           0 :     }
     260             : 
     261           0 :     fd_slot_hash_t * slot_hash = deq_fd_slot_hash_t_join( (uchar*)slot_hashes_global + slot_hashes_global->hashes_offset );
     262             : 
     263             :     /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L97 */
     264           0 :     ulong is_recent_slot = slot_hashes_position( slot_hash, create->recent_slot )!=ULONG_MAX;
     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 *     seeds[2];
     278           0 :   ulong       seed_szs[2] = { sizeof(fd_pubkey_t), sizeof(ulong) };
     279           0 :   seeds[0] = (uchar *)authority_key;
     280           0 :   seeds[1] = (uchar *)&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_bank_rent_query( ctx->txn_ctx->bank );
     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;
     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;
     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 ) ) ) {
     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;
     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;
     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 ) ) ) {
     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 const * clock = fd_sysvar_clock_read( ctx->txn_ctx->funk, ctx->txn_ctx->funk_txn, ctx->txn_ctx->spad );
     674           0 :   if( FD_UNLIKELY( !clock ) ) {
     675           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     676           0 :   }
     677             : 
     678             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L291-L299 */
     679           0 :   if( clock->slot!=state->meta.last_extended_slot ) {
     680           0 :     state->meta.last_extended_slot             = clock->slot;
     681           0 :     state->meta.last_extended_slot_start_index = (uchar)lut->addr_cnt;
     682           0 :   }
     683             : 
     684             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/address-lookup-table/src/processor.rs#L302
     685           0 :   new_table_data_sz = FD_ADDRLUT_META_SZ + new_addr_cnt * sizeof(fd_pubkey_t);
     686             : 
     687             :   /* https://github.com/anza-xyz/agave/blob/v2.2.0/programs/address-lookup-table/src/processor.rs#L286 */
     688           0 :   uchar * lut_data_mut = NULL;
     689           0 :   ulong   lut_data_mut_len = 0;
     690           0 :   err = fd_borrowed_account_get_data_mut( &lut_acct, &lut_data_mut, &lut_data_mut_len );
     691           0 :   lut_acct.acct->vt->resize( lut_acct.acct, new_table_data_sz );
     692             : 
     693             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L307-L310 */
     694           0 :   err = fd_addrlut_serialize_meta( &lut->state, lut_data_mut, lut_data_mut_len );
     695           0 :   if( FD_UNLIKELY( err ) ) {
     696           0 :     return err;
     697           0 :   }
     698             : 
     699             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L311-L313 */
     700           0 :   do {
     701           0 :     uchar * new_keys = lut_data_mut + FD_ADDRLUT_META_SZ + old_addr_cnt * sizeof(fd_pubkey_t);
     702           0 :     fd_memcpy( new_keys, extend->new_addrs, extend->new_addrs_len * sizeof(fd_pubkey_t) );
     703           0 :   } while(0);
     704           0 :   fd_borrowed_account_set_data_length( &lut_acct, new_table_data_sz );
     705           0 :   lut->addr            = (fd_pubkey_t *)(lut_data_mut + FD_ADDRLUT_META_SZ);
     706           0 :   lut->addr_cnt        = new_addr_cnt;
     707             : 
     708             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L316 */
     709           0 :   fd_borrowed_account_drop( &lut_acct );
     710             : 
     711             : 
     712             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L317-L321 */
     713           0 :   fd_rent_t const * rent              = fd_bank_rent_query( ctx->txn_ctx->bank );
     714           0 :   ulong             required_lamports = fd_rent_exempt_minimum_balance( rent, new_table_data_sz );
     715           0 :                     required_lamports = fd_ulong_max    ( required_lamports, 1UL );
     716           0 :                     required_lamports = fd_ulong_sat_sub( required_lamports, lut_lamports );
     717             : 
     718           0 :   if( required_lamports ) {
     719           0 :     fd_pubkey_t const * payer_key = NULL;
     720             : 
     721             :     /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     722             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L325-L326 */
     723           0 :     fd_guarded_borrowed_account_t payer_acct;
     724           0 :     FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_PAYER, &payer_acct );
     725             : 
     726           0 :     payer_key = payer_acct.acct->pubkey;
     727             :     /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L327-L330 */
     728           0 :     if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_PAYER ) ) ) {
     729           0 :       fd_log_collector_msg_literal( ctx, "Payer account must be a signer" );
     730           0 :       return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     731           0 :     }
     732             : 
     733             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L332 */
     734           0 :     fd_borrowed_account_drop( &payer_acct );
     735             : 
     736             : 
     737           0 :     FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) {
     738             :       // Create account metas
     739           0 :       fd_vm_rust_account_meta_t * acct_metas = (fd_vm_rust_account_meta_t *)
     740           0 :                                                 fd_spad_alloc( ctx->txn_ctx->spad, FD_VM_RUST_ACCOUNT_META_ALIGN, 2 * sizeof(fd_vm_rust_account_meta_t) );
     741           0 :       fd_native_cpi_create_account_meta( payer_key, 1, 1, &acct_metas[0] );
     742           0 :       fd_native_cpi_create_account_meta( lut_key,   0, 1, &acct_metas[1] );
     743             : 
     744             :       // Create signers list
     745           0 :       fd_pubkey_t signers[16];
     746           0 :       ulong signers_cnt = 1UL;
     747           0 :       signers[0]        = *payer_key;
     748             : 
     749             :       // Create system program instruction
     750           0 :       uchar instr_data[FD_TXN_MTU];
     751           0 :       fd_system_program_instruction_t instr = {
     752           0 :         .discriminant = fd_system_program_instruction_enum_transfer,
     753           0 :         .inner = {
     754           0 :           .transfer = required_lamports,
     755           0 :         }
     756           0 :       };
     757             : 
     758           0 :       fd_bincode_encode_ctx_t encode_ctx = {
     759           0 :         .data    = instr_data,
     760           0 :         .dataend = instr_data + FD_TXN_MTU
     761           0 :       };
     762             : 
     763             :       // This should never fail.
     764           0 :       int err = fd_system_program_instruction_encode( &instr, &encode_ctx );
     765           0 :       if( FD_UNLIKELY( err ) ) {
     766           0 :         return FD_EXECUTOR_INSTR_ERR_FATAL;
     767           0 :       }
     768             : 
     769           0 :       err = fd_native_cpi_native_invoke( ctx,
     770           0 :                                          &fd_solana_system_program_id,
     771           0 :                                          instr_data,
     772           0 :                                          FD_TXN_MTU,
     773           0 :                                          acct_metas,
     774           0 :                                          2UL,
     775           0 :                                          signers,
     776           0 :                                          signers_cnt );
     777           0 :       if( FD_UNLIKELY( err ) ) {
     778           0 :         return err;
     779           0 :       }
     780           0 :     } FD_SPAD_FRAME_END;
     781           0 :   }
     782             : 
     783           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     784             : 
     785           0 : # undef ACC_IDX_LUT
     786           0 : # undef ACC_IDX_AUTHORITY
     787           0 : # undef ACC_IDX_PAYER
     788           0 : }
     789             : 
     790             : static int
     791           0 : deactivate_lookup_table( fd_exec_instr_ctx_t * ctx ) {
     792             : 
     793           0 : # define ACC_IDX_LUT       (0UL)
     794           0 : # define ACC_IDX_AUTHORITY (1UL)
     795           0 :   int err;
     796             : 
     797             :   /* Prepare LUT account **********************************************/
     798             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L346-L351 */
     799             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
     800             : 
     801             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L347-L348 */
     802           0 :   fd_guarded_borrowed_account_t lut_acct;
     803           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     804             : 
     805             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L348-L350 */
     806           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) ) ) )
     807           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
     808             : 
     809             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L352 */
     810           0 :   fd_borrowed_account_drop( &lut_acct );
     811             : 
     812             :   /* Prepare authority account ****************************************/
     813             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L353-L360 */
     814           0 :   fd_pubkey_t const * authority_key = NULL;
     815             :   /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     816             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L354-L355 */
     817           0 :   fd_guarded_borrowed_account_t authority_acct;
     818           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_AUTHORITY, &authority_acct );
     819             : 
     820           0 :   authority_key = authority_acct.acct->pubkey;
     821             : 
     822             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L356-L359 */
     823           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_AUTHORITY ) ) ) {
     824           0 :     fd_log_collector_msg_literal( ctx, "Authority account must be a signer" );
     825           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     826           0 :   }
     827             : 
     828             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L361 */
     829           0 :   fd_borrowed_account_drop( &authority_acct );
     830             : 
     831             :   /* Update lookup table account **************************************/
     832             : 
     833             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L363-L364 */
     834           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     835             : 
     836             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L364 */
     837           0 :   uchar const * lut_data    = fd_borrowed_account_get_data( &lut_acct );
     838           0 :   ulong         lut_data_sz = fd_borrowed_account_get_data_len( &lut_acct );
     839             : 
     840             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L365 */
     841           0 :   fd_addrlut_t lut[1];
     842           0 :   err = fd_addrlut_deserialize( lut, (uchar *)lut_data, lut_data_sz );
     843           0 :   if( FD_UNLIKELY( err ) ) {
     844           0 :     return err;
     845           0 :   }
     846             : 
     847           0 :   fd_address_lookup_table_t * state = &lut->state.inner.lookup_table;
     848             : 
     849             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L367-L370 */
     850           0 :   if( FD_UNLIKELY( !state->meta.has_authority ) ) {
     851           0 :     fd_log_collector_msg_literal( ctx, "Lookup table is frozen" );
     852           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
     853           0 :   }
     854             : 
     855             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L371-L373 */
     856           0 :   if( FD_UNLIKELY( 0!=memcmp( state->meta.authority.key, authority_key->key, sizeof(fd_pubkey_t) ) ) ) {
     857           0 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
     858           0 :   }
     859             : 
     860             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L374-L377 */
     861           0 :   if( FD_UNLIKELY( state->meta.deactivation_slot != ULONG_MAX ) ) {
     862           0 :     fd_log_collector_msg_literal( ctx, "Lookup table is already deactivated" );
     863           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     864           0 :   }
     865             : 
     866             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L380 */
     867           0 :   fd_sol_sysvar_clock_t const * clock = fd_sysvar_clock_read( ctx->txn_ctx->funk, ctx->txn_ctx->funk_txn, ctx->txn_ctx->spad );
     868           0 :   if( FD_UNLIKELY( !clock ) ) {
     869           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     870           0 :   }
     871             : 
     872           0 :   uchar * data = NULL;
     873           0 :   ulong   dlen = 0UL;
     874           0 :   err = fd_borrowed_account_get_data_mut ( &lut_acct, &data, &dlen );
     875           0 :   if( FD_UNLIKELY( err ) ) {
     876           0 :     return err;
     877           0 :   }
     878             : 
     879             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L381 */
     880           0 :   state->meta.deactivation_slot = clock->slot;
     881             : 
     882             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L383-L386 */
     883           0 :   err = fd_addrlut_serialize_meta( &lut->state, data, dlen );
     884           0 :   if( FD_UNLIKELY( err ) ) {
     885           0 :     return err;
     886           0 :   }
     887             : 
     888             :   /* implicit drop of lut_acct */
     889             : 
     890           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     891             : 
     892           0 : # undef ACC_IDX_LUT
     893           0 : # undef ACC_IDX_AUTHORITY
     894           0 : }
     895             : 
     896             : static int
     897           0 : close_lookup_table( fd_exec_instr_ctx_t * ctx ) {
     898             : 
     899           0 : # define ACC_IDX_LUT       (0UL)
     900           0 : # define ACC_IDX_AUTHORITY (1UL)
     901           0 : # define ACC_IDX_RECIPIENT (2UL)
     902           0 :   int err;
     903             : 
     904             :   /* Prepare LUT account **********************************************/
     905             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L395-L400 */
     906             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
     907             : 
     908             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L396-L397 */
     909           0 :   fd_guarded_borrowed_account_t lut_acct;
     910           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     911             : 
     912             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L397-L399 */
     913           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) ) ) )
     914           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
     915             : 
     916             :     /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L401 */
     917           0 :   fd_borrowed_account_drop( &lut_acct );
     918             : 
     919             :   /* Prepare authority account ****************************************/
     920             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L402-L409 */
     921           0 :   fd_pubkey_t const * authority_key = NULL;
     922             :   /* try_borrow_account => get_index_of_instruction_account_in_transaction */
     923             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L403-L404 */
     924           0 :   fd_guarded_borrowed_account_t authority_acct;
     925           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_AUTHORITY, &authority_acct );
     926             : 
     927           0 :   authority_key = authority_acct.acct->pubkey;
     928             : 
     929             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L405-L408 */
     930           0 :   if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, ACC_IDX_AUTHORITY ) ) ) {
     931           0 :     fd_log_collector_msg_literal( ctx, "Authority account must be a signer" );
     932           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     933           0 :   }
     934             : 
     935             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L410 */
     936           0 :   fd_borrowed_account_drop( &authority_acct );
     937             : 
     938             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L411 */
     939           0 :   err = fd_exec_instr_ctx_check_num_insn_accounts( ctx, 3 );
     940           0 :   if( FD_UNLIKELY( err ) ) {
     941           0 :     return err;
     942           0 :   }
     943             : 
     944             :   /* It's ok to directly access the instruction accounts because we already verified 3 expected instruction accounts.
     945             :      https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L412-L420 */
     946           0 :   if( FD_UNLIKELY( ctx->instr->accounts[0].index_in_transaction ==
     947           0 :                    ctx->instr->accounts[2].index_in_transaction ) ) {
     948           0 :     fd_log_collector_msg_literal( ctx, "Lookup table cannot be the recipient of reclaimed lamports" );
     949           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     950           0 :   }
     951             : 
     952           0 :   ulong         withdrawn_lamports = 0UL;
     953           0 :   uchar const * lut_data           = NULL;
     954           0 :   ulong         lut_data_sz        = 0UL;
     955             : 
     956             :   /* Update lookup table account **************************************/
     957             : 
     958             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L423-L424 */
     959           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
     960             : 
     961           0 :   withdrawn_lamports = fd_borrowed_account_get_lamports( &lut_acct );
     962           0 :   lut_data           = fd_borrowed_account_get_data( &lut_acct );
     963           0 :   lut_data_sz        = fd_borrowed_account_get_data_len( &lut_acct );
     964             : 
     965             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L426 */
     966           0 :   fd_addrlut_t lut[1];
     967           0 :   err = fd_addrlut_deserialize( lut, (uchar *)lut_data, lut_data_sz );
     968           0 :   if( FD_UNLIKELY( err ) ) {
     969           0 :     return err;
     970           0 :   }
     971             : 
     972           0 :   fd_address_lookup_table_t * state = &lut->state.inner.lookup_table;
     973             : 
     974             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L428-L431 */
     975           0 :   if( FD_UNLIKELY( !state->meta.has_authority ) ) {
     976           0 :     fd_log_collector_msg_literal( ctx,  "Lookup table is frozen" );
     977           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_IMMUTABLE;
     978           0 :   }
     979             : 
     980             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L432-L434 */
     981           0 :   if( FD_UNLIKELY( 0!=memcmp( state->meta.authority.key, authority_key->key, sizeof(fd_pubkey_t) ) ) ) {
     982           0 :     return FD_EXECUTOR_INSTR_ERR_INCORRECT_AUTHORITY;
     983           0 :   }
     984             : 
     985             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L437 */
     986           0 :   fd_sol_sysvar_clock_t const * clock = fd_sysvar_clock_read( ctx->txn_ctx->funk, ctx->txn_ctx->funk_txn, ctx->txn_ctx->spad );
     987           0 :   if( FD_UNLIKELY( !clock ) ) {
     988           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     989           0 :   }
     990             : 
     991             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L438 */
     992           0 :   fd_slot_hashes_global_t const * slot_hashes_global = fd_sysvar_slot_hashes_read( ctx->txn_ctx->funk, ctx->txn_ctx->funk_txn, ctx->txn_ctx->spad );
     993           0 :   if( FD_UNLIKELY( !slot_hashes_global ) ) {
     994           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     995           0 :   }
     996             : 
     997           0 :   fd_slot_hash_t * slot_hash = deq_fd_slot_hash_t_join( (uchar*)slot_hashes_global + slot_hashes_global->hashes_offset );
     998             : 
     999             :   /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L440 */
    1000           0 :   ulong remaining_blocks = 0UL;
    1001           0 :   int status = fd_addrlut_status( &state->meta, clock->slot, slot_hash, &remaining_blocks );
    1002             : 
    1003           0 :   switch( status ) {
    1004           0 :     case FD_ADDRLUT_STATUS_ACTIVATED:
    1005           0 :       fd_log_collector_msg_literal( ctx, "Lookup table is not deactivated" );
    1006           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1007           0 :     case FD_ADDRLUT_STATUS_DEACTIVATING:
    1008             :       /* Max msg_sz: 65 - 3 + 20 = 82 < 127 => we can use printf */
    1009           0 :       fd_log_collector_printf_dangerous_max_127( ctx,
    1010           0 :         "Table cannot be closed until it's fully deactivated in %lu blocks", remaining_blocks );
    1011           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1012           0 :     case FD_ADDRLUT_STATUS_DEACTIVATED:
    1013           0 :       break;
    1014           0 :     default:
    1015           0 :       __builtin_unreachable();
    1016           0 :   }
    1017             : 
    1018             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L456 */
    1019           0 :   fd_borrowed_account_drop( &lut_acct );
    1020             : 
    1021             :   /* Add lamports to recipient ****************************************/
    1022             :   /* try_borrow_instruction_account => get_index_of_instruction_account_in_transaction */
    1023             : 
    1024             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L458-L459 */
    1025           0 :   fd_guarded_borrowed_account_t recipient_acct;
    1026           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_RECIPIENT, &recipient_acct );
    1027             : 
    1028           0 :   err = fd_borrowed_account_checked_add_lamports( &recipient_acct, withdrawn_lamports );
    1029           0 :   if( FD_UNLIKELY( err ) ) {
    1030           0 :     return err;
    1031           0 :   }
    1032             : 
    1033             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L461 */
    1034           0 :   fd_borrowed_account_drop( &recipient_acct );
    1035             : 
    1036             :   /* Delete LUT account ***********************************************/
    1037             : 
    1038             :   /* https://github.com/anza-xyz/agave/blob/v2.1.4/programs/address-lookup-table/src/processor.rs#L463-L464 */
    1039           0 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, ACC_IDX_LUT, &lut_acct );
    1040             : 
    1041           0 :   err = fd_borrowed_account_set_data_length( &lut_acct, 0UL );
    1042           0 :   if( FD_UNLIKELY( err ) ) {
    1043           0 :     return err;
    1044           0 :   }
    1045             : 
    1046           0 :   err = fd_borrowed_account_set_lamports( &lut_acct, 0UL );
    1047           0 :   if( FD_UNLIKELY( err ) ) {
    1048           0 :     return err;
    1049           0 :   }
    1050             : 
    1051           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1052             : 
    1053           0 : # undef ACC_IDX_LUT
    1054           0 : # undef ACC_IDX_AUTHORITY
    1055           0 : # undef ACC_IDX_RECIPIENT
    1056           0 : }
    1057             : 
    1058             : int
    1059           0 : fd_address_lookup_table_program_execute( fd_exec_instr_ctx_t * ctx ) {
    1060             :   /* Prevent execution of migrated native programs */
    1061           0 :   if( FD_UNLIKELY( FD_FEATURE_ACTIVE_BANK( ctx->txn_ctx->bank, migrate_address_lookup_table_program_to_core_bpf ) ) ) {
    1062           0 :     return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    1063           0 :   }
    1064             : 
    1065           0 :   FD_EXEC_CU_UPDATE( ctx, DEFAULT_COMPUTE_UNITS );
    1066             : 
    1067           0 :   uchar const * instr_data    = ctx->instr->data;
    1068           0 :   ulong         instr_data_sz = ctx->instr->data_sz;
    1069           0 :   if( FD_UNLIKELY( instr_data==NULL ) ) {
    1070           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1071           0 :   }
    1072             : 
    1073           0 :   FD_SPAD_FRAME_BEGIN( ctx->txn_ctx->spad ) {
    1074             :     /* https://github.com/solana-labs/solana/blob/v1.17.4/programs/address-lookup-table/src/processor.rs#L28 */
    1075           0 :     ulong decoded_sz;
    1076           0 :     fd_addrlut_instruction_t * instr = fd_bincode_decode1_spad(
    1077           0 :         addrlut_instruction, ctx->txn_ctx->spad,
    1078           0 :         instr_data, instr_data_sz,
    1079           0 :         NULL,
    1080           0 :         &decoded_sz );
    1081           0 :     if( FD_UNLIKELY( !instr || decoded_sz > FD_TXN_MTU ) ) {
    1082           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1083           0 :     }
    1084             : 
    1085           0 :     switch( instr->discriminant ) {
    1086           0 :     case fd_addrlut_instruction_enum_create_lut:
    1087           0 :       return create_lookup_table( ctx, &instr->inner.create_lut );
    1088           0 :     case fd_addrlut_instruction_enum_freeze_lut:
    1089           0 :       return freeze_lookup_table( ctx );
    1090           0 :     case fd_addrlut_instruction_enum_extend_lut:
    1091           0 :       return extend_lookup_table( ctx, &instr->inner.extend_lut );
    1092           0 :     case fd_addrlut_instruction_enum_deactivate_lut:
    1093           0 :       return deactivate_lookup_table( ctx );
    1094           0 :     case fd_addrlut_instruction_enum_close_lut:
    1095           0 :       return close_lookup_table( ctx );
    1096           0 :     default:
    1097           0 :       break;
    1098           0 :     }
    1099           0 :   } FD_SPAD_FRAME_END;
    1100             : 
    1101           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1102           0 : }
    1103             : 
    1104             : /**********************************************************************/
    1105             : /* Public API                                                         */
    1106             : /**********************************************************************/
    1107             : 
    1108             : /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L72-L78 */
    1109             : static uchar
    1110             : is_active( fd_address_lookup_table_t const * self,
    1111             :            ulong                             current_slot,
    1112           0 :            fd_slot_hash_t const *            slot_hashes ) {
    1113             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L73-L77 */
    1114           0 :   ulong _dummy[1];
    1115           0 :   switch( fd_addrlut_status( &self->meta, current_slot, slot_hashes, _dummy ) ) {
    1116           0 :     case FD_ADDRLUT_STATUS_ACTIVATED:
    1117           0 :     case FD_ADDRLUT_STATUS_DEACTIVATING:
    1118           0 :       return 1;
    1119           0 :     case FD_ADDRLUT_STATUS_DEACTIVATED:
    1120           0 :       return 0;
    1121           0 :     default:
    1122           0 :       __builtin_unreachable();
    1123           0 :   }
    1124           0 : }
    1125             : 
    1126             : /* Sets active_addresses_len on success
    1127             :    https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L142-L164 */
    1128             : int
    1129             : fd_get_active_addresses_len( fd_address_lookup_table_t * self,
    1130             :                              ulong                       current_slot,
    1131             :                              fd_slot_hash_t const *      slot_hashes,
    1132             :                              ulong                       addresses_len,
    1133           0 :                              ulong *                     active_addresses_len ) {
    1134             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L147-L152 */
    1135           0 :   if( FD_UNLIKELY( !is_active( self, current_slot, slot_hashes ) ) ) {
    1136           0 :     return FD_RUNTIME_TXN_ERR_ADDRESS_LOOKUP_TABLE_NOT_FOUND;
    1137           0 :   }
    1138             : 
    1139             :   /* https://github.com/anza-xyz/agave/blob/368ea563c423b0a85cc317891187e15c9a321521/sdk/program/src/address_lookup_table/state.rs#L157-L161 */
    1140           0 :   *active_addresses_len = ( current_slot > self->meta.last_extended_slot )
    1141           0 :       ? addresses_len
    1142           0 :       : self->meta.last_extended_slot_start_index;
    1143             : 
    1144           0 :   return FD_RUNTIME_EXECUTE_SUCCESS;
    1145           0 : }

Generated by: LCOV version 1.14