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

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

Generated by: LCOV version 1.14