LCOV - code coverage report
Current view: top level - disco/bank - fd_bank_abi.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 191 0.0 %
Date: 2025-03-10 12:29:05 Functions: 0 4 0.0 %

          Line data    Source code
       1             : 
       2             : #include "fd_bank_abi.h"
       3             : #include "../../flamenco/runtime/fd_system_ids_pp.h"
       4             : #include "../../flamenco/runtime/fd_system_ids.h"
       5             : #include "../../flamenco/types/fd_types.h"
       6             : 
       7             : #define ABI_ALIGN( x ) __attribute__((packed)) __attribute__((aligned(x)))
       8             : 
       9             : #define MAP_PERFECT_NAME      fd_bank_abi_builtin_keys_and_sysvars_tbl
      10             : #define MAP_PERFECT_LG_TBL_SZ 5
      11             : #define MAP_PERFECT_T         fd_acct_addr_t
      12           0 : #define MAP_PERFECT_HASH_C    1402126759U
      13             : #define MAP_PERFECT_KEY       b
      14             : #define MAP_PERFECT_KEY_T     fd_acct_addr_t const *
      15             : #define MAP_PERFECT_ZERO_KEY  (0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0)
      16             : #define MAP_PERFECT_COMPLEX_KEY 1
      17           0 : #define MAP_PERFECT_KEYS_EQUAL(k1,k2) (!memcmp( (k1), (k2), 32UL ))
      18             : 
      19           0 : #define PERFECT_HASH( u ) (((MAP_PERFECT_HASH_C*(u))>>27)&0x1FU)
      20             : 
      21             : #define MAP_PERFECT_HASH_PP( a00,a01,a02,a03,a04,a05,a06,a07,a08,a09,a10,a11,a12,a13,a14,a15, \
      22             :                              a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31) \
      23             :                                           PERFECT_HASH( (a08 | (a09<<8) | (a10<<16) | (a11<<24)) )
      24           0 : #define MAP_PERFECT_HASH_R( ptr ) PERFECT_HASH( fd_uint_load_4( (uchar const *)ptr->b + 8UL ) )
      25             : 
      26             : /* This list is exactly what Lab's is_builtin_key_or_sysvar checks. */
      27             : /* Sysvars */
      28             : #define MAP_PERFECT_0  ( SYSVAR_CLOCK_ID          ),
      29             : #define MAP_PERFECT_1  ( SYSVAR_EPOCH_SCHED_ID    ),
      30             : #define MAP_PERFECT_2  ( SYSVAR_FEES_ID           ),
      31             : #define MAP_PERFECT_3  ( SYSVAR_RECENT_BLKHASH_ID ),
      32             : #define MAP_PERFECT_4  ( SYSVAR_RENT_ID           ),
      33             : #define MAP_PERFECT_5  ( SYSVAR_REWARDS_ID        ),
      34             : #define MAP_PERFECT_6  ( SYSVAR_SLOT_HASHES_ID    ),
      35             : #define MAP_PERFECT_7  ( SYSVAR_SLOT_HIST_ID      ),
      36             : #define MAP_PERFECT_8  ( SYSVAR_STAKE_HIST_ID     ),
      37             : #define MAP_PERFECT_9  ( SYSVAR_INSTRUCTIONS_ID   ),
      38             : #define MAP_PERFECT_10 ( SYSVAR_EPOCH_REWARDS_ID  ),
      39             : #define MAP_PERFECT_11 ( SYSVAR_LAST_RESTART_ID   ),
      40             : /* Programs */
      41             : #define MAP_PERFECT_12 ( CONFIG_PROG_ID           ),
      42             : #define MAP_PERFECT_13 ( FEATURE_ID               ),
      43             : #define MAP_PERFECT_14 ( NATIVE_LOADER_ID         ),
      44             : #define MAP_PERFECT_15 ( STAKE_PROG_ID            ),
      45             : #define MAP_PERFECT_16 ( STAKE_CONFIG_PROG_ID     ),
      46             : #define MAP_PERFECT_17 ( VOTE_PROG_ID             ),
      47             : #define MAP_PERFECT_18 ( SYS_PROG_ID              ),
      48             : #define MAP_PERFECT_19 ( BPF_LOADER_1_PROG_ID     ),
      49             : #define MAP_PERFECT_20 ( BPF_LOADER_2_PROG_ID     ),
      50             : #define MAP_PERFECT_21 ( BPF_UPGRADEABLE_PROG_ID  ),
      51             : 
      52             : #include "../../util/tmpl/fd_map_perfect.c"
      53             : 
      54             : typedef struct ABI_ALIGN(1UL) {
      55             :   uchar key[ 32UL ];
      56             : } sanitized_txn_abi_pubkey_t;
      57             : 
      58             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_pubkey_t) == 32UL, "messed up size" );
      59             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_pubkey_t) == 1UL, "messed up size" );
      60             : 
      61             : typedef struct ABI_ALIGN(1UL) {
      62             :   uchar signature[ 64UL ];
      63             : } sanitized_txn_abi_signature_t;
      64             : 
      65             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_signature_t) == 64UL, "messed up size" );
      66             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_signature_t) == 1UL, "messed up size" );
      67             : 
      68             : typedef struct ABI_ALIGN(8UL) {
      69             :   ulong   accounts_cap;
      70             :   uchar * accounts;
      71             :   ulong   accounts_cnt;
      72             : 
      73             :   ulong   data_cap;
      74             :   uchar * data;
      75             :   ulong   data_cnt;
      76             : 
      77             :   uchar program_id_index;
      78             : } sanitized_txn_abi_compiled_instruction_t;
      79             : 
      80             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_compiled_instruction_t) == 56UL, "messed up size" );
      81             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_compiled_instruction_t) == 8UL, "messed up size" );
      82             : 
      83             : typedef struct ABI_ALIGN(1UL) {
      84             :   uchar num_required_signatures;
      85             :   uchar num_readonly_signed_accounts;
      86             :   uchar num_readonly_unsigned_accounts;
      87             : } sanitized_txn_abi_message_header_t;
      88             : 
      89             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_message_header_t) == 3UL, "messed up size" );
      90             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_message_header_t) == 1UL, "messed up size" );
      91             : 
      92             : typedef struct ABI_ALIGN(8UL) {
      93             :   ulong account_keys_cap;
      94             :   sanitized_txn_abi_pubkey_t * account_keys;
      95             :   ulong account_keys_cnt;
      96             : 
      97             :   ulong instructions_cap;
      98             :   sanitized_txn_abi_compiled_instruction_t * instructions;
      99             :   ulong instructions_cnt;
     100             : 
     101             :   uchar recent_blockhash[ 32 ];
     102             : 
     103             :   sanitized_txn_abi_message_header_t header;
     104             : } sanitized_txn_abi_legacy_message0_t;
     105             : 
     106             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_legacy_message0_t) == 88UL, "messed up size" );
     107             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_legacy_message0_t) == 8UL, "messed up size" );
     108             : 
     109             : typedef struct ABI_ALIGN(8UL) {
     110             :   ulong   is_writable_account_cache_cap;
     111             :   uchar * is_writable_account_cache;
     112             :   ulong   is_writable_account_cache_cnt;
     113             : 
     114             :   union __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     115             :     struct __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     116             :       ulong tag; /* Niche tag encoding.  Value 0 is borrowed, nonzero is owned. */
     117             :       sanitized_txn_abi_legacy_message0_t * borrowed;
     118             :     };
     119             : 
     120             :     struct __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     121             :       sanitized_txn_abi_legacy_message0_t owned;
     122             :     };
     123             :   } message;
     124             : } sanitized_txn_abi_legacy_message1_t;
     125             : 
     126             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_legacy_message1_t) == 112UL, "messed up size" );
     127             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_legacy_message1_t) == 8UL, "messed up size" );
     128             : 
     129             : typedef struct ABI_ALIGN(8UL) {
     130             :   ulong   writable_indexes_cap;
     131             :   uchar * writable_indexes;
     132             :   ulong   writable_indexes_cnt;
     133             : 
     134             :   ulong   readonly_indexes_cap;
     135             :   uchar * readonly_indexes;
     136             :   ulong   readonly_indexes_cnt;
     137             : 
     138             :   uchar account_key[ 32 ];
     139             : } sanitized_txn_abi_v0_message_address_table_lookup_t;
     140             : 
     141             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_v0_message_address_table_lookup_t) == 80UL, "messed up size" );
     142             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_v0_message_address_table_lookup_t) == 8UL, "messed up size" );
     143             : 
     144             : typedef struct ABI_ALIGN(8UL) {
     145             :   ulong                        account_keys_cap;
     146             :   sanitized_txn_abi_pubkey_t * account_keys;
     147             :   ulong                        account_keys_cnt;
     148             : 
     149             :   ulong                                      instructions_cap;
     150             :   sanitized_txn_abi_compiled_instruction_t * instructions;
     151             :   ulong                                      instructions_cnt;
     152             : 
     153             :   ulong                                                 address_table_lookups_cap;
     154             :   sanitized_txn_abi_v0_message_address_table_lookup_t * address_table_lookups;
     155             :   ulong                                                 address_table_lookups_cnt;
     156             : 
     157             :   uchar recent_blockhash[ 32 ];
     158             : 
     159             :   sanitized_txn_abi_message_header_t header;
     160             : } sanitized_txn_abi_v0_message_t;
     161             : 
     162             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_v0_message_t) == 112UL, "messed up size" );
     163             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_v0_message_t) == 8UL, "messed up size" );
     164             : 
     165             : typedef struct ABI_ALIGN(8UL) {
     166             :   ulong                        writable_cap;
     167             :   sanitized_txn_abi_pubkey_t * writable;
     168             :   ulong                        writable_cnt;
     169             : 
     170             :   ulong                        readable_cap;
     171             :   sanitized_txn_abi_pubkey_t * readable;
     172             :   ulong                        readable_cnt;
     173             : } sanitized_txn_abi_v0_loaded_addresses_t;
     174             : 
     175             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_v0_loaded_addresses_t) == 48UL, "messed up size" );
     176             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_v0_loaded_addresses_t) == 8UL, "messed up size" );
     177             : 
     178             : typedef struct ABI_ALIGN(8UL) {
     179             :   ulong   is_writable_account_cache_cap;
     180             :   uchar * is_writable_account_cache;
     181             :   ulong   is_writable_account_cache_cnt;
     182             : 
     183             :   union __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     184             :     struct __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     185             :       ulong tag; /* Niche tag encoding.  Value 0 is borrowed, nonzero is owned. */
     186             :       sanitized_txn_abi_v0_message_t * borrowed;
     187             :     };
     188             : 
     189             :     struct __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     190             :       sanitized_txn_abi_v0_message_t owned;
     191             :     };
     192             :   } message;
     193             : 
     194             :   union __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     195             :     struct __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     196             :       ulong tag; /* Niche tag encoding.  Value 0 is borrowed, nonzero is owned. */
     197             :       sanitized_txn_abi_v0_loaded_addresses_t * borrowed;
     198             :     };
     199             : 
     200             :     struct __attribute__((__packed__)) __attribute__((aligned(8UL))) {
     201             :       sanitized_txn_abi_v0_loaded_addresses_t owned;
     202             :     };
     203             :   } loaded_addresses;
     204             : } sanitized_txn_abi_v0_loaded_msg_t;
     205             : 
     206             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_v0_loaded_msg_t) == 184UL, "messed up size" );
     207             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_v0_loaded_msg_t) == 8UL, "messed up size" );
     208             : 
     209             : typedef union ABI_ALIGN(8UL) {
     210             :   struct ABI_ALIGN(8UL) {
     211             :     ulong tag; /* Niche tag encoding.  Value 0 is legacy, nonzero is v0. */
     212             :     sanitized_txn_abi_legacy_message1_t legacy;
     213             :   };
     214             : 
     215             :   sanitized_txn_abi_v0_loaded_msg_t v0; /* No tag. First field is always non-NULL, so rustc can disciminate from legacy. */
     216             : } sanitized_txn_abi_message_t;
     217             : 
     218             : FD_STATIC_ASSERT( sizeof(sanitized_txn_abi_message_t) == 184UL, "messed up size" );
     219             : FD_STATIC_ASSERT( alignof(sanitized_txn_abi_message_t) == 8UL, "messed up size" );
     220             : 
     221             : FD_STATIC_ASSERT( offsetof(sanitized_txn_abi_message_t, v0) == 0UL, "messed up size" );
     222             : FD_STATIC_ASSERT( offsetof(sanitized_txn_abi_message_t, legacy) == 8UL, "messed up size" );
     223             : 
     224             : struct ABI_ALIGN(8UL) fd_bank_abi_txn_private {
     225             :   ulong                           signatures_cap;
     226             :   sanitized_txn_abi_signature_t * signatures;
     227             :   ulong                           signatures_cnt;
     228             : 
     229             :   sanitized_txn_abi_message_t message;
     230             : 
     231             :   uchar message_hash[ 32 ];
     232             :   uchar is_simple_vote_tx;
     233             : };
     234             : 
     235             : FD_STATIC_ASSERT( sizeof(struct fd_bank_abi_txn_private) == 248UL, "messed up size" );
     236             : FD_STATIC_ASSERT( alignof(struct fd_bank_abi_txn_private) == 8UL, "messed up size" );
     237             : 
     238             : FD_STATIC_ASSERT( offsetof(struct fd_bank_abi_txn_private, signatures) == 8UL, "messed up size" );
     239             : FD_STATIC_ASSERT( offsetof(struct fd_bank_abi_txn_private, message) == 24UL, "messed up size" );
     240             : FD_STATIC_ASSERT( offsetof(struct fd_bank_abi_txn_private, message_hash) == 208UL, "messed up size" );
     241             : FD_STATIC_ASSERT( offsetof(struct fd_bank_abi_txn_private, is_simple_vote_tx) == 240UL, "messed up size" );
     242             : 
     243             : static int
     244             : is_key_called_as_program( fd_txn_t const * txn,
     245           0 :                           ushort           key_index ) {
     246           0 :   for( ushort i=0; i<txn->instr_cnt; i++ ) {
     247           0 :     fd_txn_instr_t const * instr = &txn->instr[ i ];
     248           0 :     if( FD_UNLIKELY( instr->program_id==key_index ) ) return 1;
     249           0 :   }
     250           0 :   return 0;
     251           0 : }
     252             : 
     253             : static const uchar BPF_UPGRADEABLE_PROG_ID1[32] = { BPF_UPGRADEABLE_PROG_ID };
     254             : 
     255             : static int
     256             : is_upgradeable_loader_present( fd_txn_t const *                   txn,
     257             :                                uchar const *                      payload,
     258           0 :                                sanitized_txn_abi_pubkey_t const * loaded_addresses ) {
     259           0 :   for( ushort i=0; i<txn->acct_addr_cnt; i++ ) {
     260           0 :     if( FD_UNLIKELY( !memcmp( payload + txn->acct_addr_off + i*32UL, BPF_UPGRADEABLE_PROG_ID1, 32UL ) ) ) return 1;
     261           0 :   }
     262           0 :   for( ushort i=0; i<txn->addr_table_adtl_cnt; i++ ) {
     263           0 :     if( FD_UNLIKELY( !memcmp( loaded_addresses + i, BPF_UPGRADEABLE_PROG_ID1, 32UL ) ) ) return 1;
     264           0 :   }
     265           0 :   return 0;
     266           0 : }
     267             : 
     268             : extern int
     269             : fd_ext_bank_load_account( void const *  bank,
     270             :                           int           fixed_root,
     271             :                           uchar const * addr,
     272             :                           uchar *       owner,
     273             :                           uchar *       data,
     274             :                           ulong *       data_sz );
     275             : 
     276             : int
     277             : fd_bank_abi_resolve_address_lookup_tables( void const *     bank,
     278             :                                            int              fixed_root,
     279             :                                            ulong            slot,
     280             :                                            fd_txn_t const * txn,
     281             :                                            uchar const *    payload,
     282           0 :                                            fd_acct_addr_t * out_lut_accts ) {
     283           0 :   ulong writable_idx = 0UL;
     284           0 :   ulong readable_idx = 0UL;
     285           0 :   for( ulong i=0UL; i<txn->addr_table_lookup_cnt; i++ ) {
     286           0 :     fd_txn_acct_addr_lut_t const * lut = &fd_txn_get_address_tables_const( txn )[ i ];
     287           0 :     uchar const * addr = payload + lut->addr_off;
     288             : 
     289           0 :     uchar owner[ 32UL ];
     290           0 :     uchar data[ 1UL+56UL+256UL*32UL ];
     291           0 :     ulong data_sz = sizeof(data);
     292           0 :     int result = fd_ext_bank_load_account( bank, fixed_root, addr, owner, data, &data_sz );
     293           0 :     if( FD_UNLIKELY( result ) ) return FD_BANK_ABI_TXN_INIT_ERR_ACCOUNT_NOT_FOUND;
     294             : 
     295           0 :     result = memcmp( owner, fd_solana_address_lookup_table_program_id.key, 32UL );
     296           0 :     if( FD_UNLIKELY( result ) ) return FD_BANK_ABI_TXN_INIT_ERR_INVALID_ACCOUNT_OWNER;
     297             : 
     298           0 :     if( FD_UNLIKELY( (data_sz<56UL) | (data_sz>(56UL+256UL*32UL)) ) ) return FD_BANK_ABI_TXN_INIT_ERR_INVALID_ACCOUNT_DATA;
     299             : 
     300           0 :     fd_bincode_decode_ctx_t bincode = {
     301           0 :       .data    = data,
     302           0 :       .dataend = data+data_sz,
     303           0 :     };
     304             : 
     305           0 :     ulong total_sz = 0UL;
     306           0 :     result = fd_address_lookup_table_state_decode_footprint( &bincode, &total_sz );
     307           0 :     if( FD_UNLIKELY( result!=FD_BINCODE_SUCCESS ) ) return FD_BANK_ABI_TXN_INIT_ERR_INVALID_ACCOUNT_DATA;
     308             : 
     309           0 :     fd_address_lookup_table_state_t table[1];
     310           0 :     fd_address_lookup_table_state_decode( table, &bincode );
     311             : 
     312           0 :     result = fd_address_lookup_table_state_is_lookup_table( table );
     313           0 :     if( FD_UNLIKELY( !result ) ) return FD_BANK_ABI_TXN_INIT_ERR_ACCOUNT_UNINITIALIZED;
     314             : 
     315           0 :     if( FD_UNLIKELY( (data_sz-56UL)%32UL ) ) return FD_BANK_ABI_TXN_INIT_ERR_INVALID_ACCOUNT_DATA;
     316             : 
     317           0 :     ulong addresses_len = (data_sz-56UL)/32UL;
     318           0 :     fd_acct_addr_t const * addresses = fd_type_pun_const( data+56UL );
     319             : 
     320             :     /* This logic is not currently very precise... an ALUT is allowed if
     321             :        the deactivation slot is no longer present in the slot hashes
     322             :        sysvar, which means that the slot was more than 512 *unskipped*
     323             :        slots prior.  In the current case, we are just throwing out a
     324             :        fraction of transactions that could actually still be valid
     325             :        (those deactivated between 512 and 512*(1+skip_rate) slots ago. */
     326             : 
     327           0 :     ulong deactivation_slot = table->inner.lookup_table.meta.deactivation_slot;
     328           0 :     if( FD_UNLIKELY( deactivation_slot!=ULONG_MAX && (deactivation_slot+512UL)<slot ) ) return FD_BANK_ABI_TXN_INIT_ERR_ACCOUNT_NOT_FOUND;
     329             : 
     330           0 :     ulong active_addresses_len = fd_ulong_if( slot>table->inner.lookup_table.meta.last_extended_slot,
     331           0 :                                               addresses_len,
     332           0 :                                               table->inner.lookup_table.meta.last_extended_slot_start_index );
     333           0 :     for( ulong j=0UL; j<lut->writable_cnt; j++ ) {
     334           0 :       uchar idx = payload[ lut->writable_off+j ];
     335           0 :       if( FD_UNLIKELY( idx>=active_addresses_len ) ) return FD_BANK_ABI_TXN_INIT_ERR_INVALID_LOOKUP_INDEX;
     336           0 :       memcpy( &out_lut_accts[ writable_idx++ ], addresses+idx, sizeof(fd_acct_addr_t) );
     337           0 :     }
     338           0 :     for( ulong j=0UL; j<lut->readonly_cnt; j++ ) {
     339           0 :       uchar idx = payload[ lut->readonly_off+j ];
     340           0 :       if( FD_UNLIKELY( idx>=active_addresses_len ) ) return FD_BANK_ABI_TXN_INIT_ERR_INVALID_LOOKUP_INDEX;
     341           0 :       memcpy( &out_lut_accts[ txn->addr_table_adtl_writable_cnt+readable_idx++ ], addresses+idx, sizeof(fd_acct_addr_t) );
     342           0 :     }
     343           0 :   }
     344             : 
     345           0 :   return FD_BANK_ABI_TXN_INIT_SUCCESS;
     346           0 : }
     347             : 
     348             : int
     349             : fd_bank_abi_txn_init( fd_bank_abi_txn_t * out_txn,
     350             :                       uchar *             out_sidecar,
     351             :                       void const *        bank,
     352             :                       ulong               slot,
     353             :                       fd_blake3_t *       blake3,
     354             :                       uchar *             payload,
     355             :                       ulong               payload_sz,
     356             :                       fd_txn_t *          txn,
     357           0 :                       int                 is_simple_vote ) {
     358           0 :   out_txn->signatures_cnt = txn->signature_cnt;
     359           0 :   out_txn->signatures_cap = txn->signature_cnt;
     360           0 :   out_txn->signatures     = (void*)(payload + txn->signature_off);
     361             : 
     362           0 :   fd_blake3_init( blake3 );
     363           0 :   fd_blake3_append( blake3, "solana-tx-message-v1", 20UL );
     364           0 :   fd_blake3_append( blake3, payload + txn->message_off, payload_sz - txn->message_off );
     365           0 :   fd_blake3_fini( blake3, out_txn->message_hash );
     366             : 
     367           0 :   out_txn->is_simple_vote_tx = !!is_simple_vote;
     368             : 
     369           0 :   if( FD_LIKELY( txn->transaction_version==FD_TXN_VLEGACY ) ) {
     370           0 :     sanitized_txn_abi_legacy_message1_t * legacy = &out_txn->message.legacy;
     371           0 :     sanitized_txn_abi_legacy_message0_t * message = &legacy->message.owned;
     372             : 
     373           0 :     out_txn->message.tag = 9223372036854775808UL;
     374             : 
     375           0 :     legacy->is_writable_account_cache_cnt = txn->acct_addr_cnt;
     376           0 :     legacy->is_writable_account_cache_cap = txn->acct_addr_cnt;
     377           0 :     legacy->is_writable_account_cache     = out_sidecar;
     378           0 :     int _is_upgradeable_loader_present = is_upgradeable_loader_present( txn, payload, NULL );
     379           0 :     for( ushort i=0; i<txn->acct_addr_cnt; i++ ) {
     380           0 :       int is_writable = fd_txn_is_writable( txn, i ) &&
     381             :                         /* Agave does this check, but we don't need to here because pack
     382             :                            rejects these transactions before they make it to the bank.
     383             : 
     384             :                            !fd_bank_abi_builtin_keys_and_sysvars_tbl_contains( (const fd_acct_addr_t*)(payload + txn->acct_addr_off + i*32UL) ) */
     385           0 :                         (!is_key_called_as_program( txn, i ) || _is_upgradeable_loader_present);
     386           0 :       legacy->is_writable_account_cache[ i ] = !!is_writable;
     387           0 :     }
     388           0 :     out_sidecar += txn->acct_addr_cnt;
     389           0 :     out_sidecar = (void*)fd_ulong_align_up( (ulong)out_sidecar, 8UL );
     390             : 
     391           0 :     message->account_keys_cnt = txn->acct_addr_cnt;
     392           0 :     message->account_keys_cap = txn->acct_addr_cnt;
     393           0 :     message->account_keys     = (void*)(payload + txn->acct_addr_off);
     394             : 
     395           0 :     message->instructions_cnt = txn->instr_cnt;
     396           0 :     message->instructions_cap = txn->instr_cnt;
     397           0 :     message->instructions     = (void*)out_sidecar;
     398           0 :     for( ulong i=0; i<txn->instr_cnt; i++ ) {
     399           0 :       fd_txn_instr_t * instr = &txn->instr[ i ];
     400           0 :       sanitized_txn_abi_compiled_instruction_t * out_instr = &message->instructions[ i ];
     401             : 
     402           0 :       out_instr->accounts_cnt = instr->acct_cnt;
     403           0 :       out_instr->accounts_cap = instr->acct_cnt;
     404           0 :       out_instr->accounts     = payload + instr->acct_off;
     405             : 
     406           0 :       out_instr->data_cnt = instr->data_sz;
     407           0 :       out_instr->data_cap = instr->data_sz;
     408           0 :       out_instr->data     = payload + instr->data_off;
     409             : 
     410           0 :       out_instr->program_id_index = instr->program_id;
     411           0 :     }
     412           0 :     out_sidecar += txn->instr_cnt*sizeof(sanitized_txn_abi_compiled_instruction_t);
     413             : 
     414           0 :     fd_memcpy( message->recent_blockhash, payload + txn->recent_blockhash_off, 32UL );
     415           0 :     message->header.num_required_signatures        = txn->signature_cnt;
     416           0 :     message->header.num_readonly_signed_accounts   = txn->readonly_signed_cnt;
     417           0 :     message->header.num_readonly_unsigned_accounts = txn->readonly_unsigned_cnt;
     418           0 :     return FD_BANK_ABI_TXN_INIT_SUCCESS;
     419           0 :   } else if( FD_LIKELY( txn->transaction_version==FD_TXN_V0 ) ){
     420           0 :     sanitized_txn_abi_v0_loaded_msg_t * v0 = &out_txn->message.v0;
     421           0 :     sanitized_txn_abi_v0_loaded_addresses_t * loaded_addresses = &v0->loaded_addresses.owned;
     422           0 :     sanitized_txn_abi_v0_message_t * message = &v0->message.owned;
     423             : 
     424           0 :     int result = fd_bank_abi_resolve_address_lookup_tables( bank, 1, slot, txn, payload, (fd_acct_addr_t*)out_sidecar );
     425           0 :     if( FD_UNLIKELY( result!=FD_BANK_ABI_TXN_INIT_SUCCESS ) ) return result;
     426             : 
     427           0 :     ulong lut_writable_acct_cnt = fd_txn_account_cnt( txn, FD_TXN_ACCT_CAT_WRITABLE_ALT );
     428           0 :     loaded_addresses->writable_cnt = lut_writable_acct_cnt;
     429           0 :     loaded_addresses->writable_cap = lut_writable_acct_cnt;
     430           0 :     loaded_addresses->writable     = (sanitized_txn_abi_pubkey_t*)out_sidecar;
     431           0 :     out_sidecar += 32UL*lut_writable_acct_cnt;
     432             : 
     433           0 :     ulong lut_readonly_acct_cnt = fd_txn_account_cnt( txn, FD_TXN_ACCT_CAT_READONLY_ALT );
     434           0 :     loaded_addresses->readable_cnt = lut_readonly_acct_cnt;
     435           0 :     loaded_addresses->readable_cap = lut_readonly_acct_cnt;
     436           0 :     loaded_addresses->readable     = (sanitized_txn_abi_pubkey_t*)out_sidecar;
     437           0 :     out_sidecar += 32UL*lut_readonly_acct_cnt;
     438             : 
     439           0 :     ulong total_acct_cnt = fd_txn_account_cnt( txn, FD_TXN_ACCT_CAT_ALL );
     440           0 :     v0->is_writable_account_cache_cnt = total_acct_cnt;
     441           0 :     v0->is_writable_account_cache_cap = total_acct_cnt;
     442           0 :     v0->is_writable_account_cache     = out_sidecar;
     443             : 
     444             :     /* This looks like it will be an OOB read because we are passing
     445             :        just the writable account hashes, but the readable ones are
     446             :        immediately after them in memory, so it's ok. */
     447           0 :     int _is_upgradeable_loader_present = is_upgradeable_loader_present( txn, payload, loaded_addresses->writable );
     448           0 :     for( ushort i=0; i<txn->acct_addr_cnt; i++ ) {
     449           0 :       int is_writable = fd_txn_is_writable( txn, i ) &&
     450             :                         /* Agave does this check, but we don't need to here because pack
     451             :                            rejects these transactions before they make it to the bank.
     452             : 
     453             :                            !fd_bank_abi_builtin_keys_and_sysvars_tbl_contains( (const fd_acct_addr_t*)(payload + txn->acct_addr_off + i*32UL) ) */
     454           0 :                         (!is_key_called_as_program( txn, i ) || _is_upgradeable_loader_present);
     455           0 :       v0->is_writable_account_cache[ i ] = !!is_writable;
     456           0 :     }
     457           0 :     for( ushort i=0; i<txn->addr_table_adtl_writable_cnt; i++ ) {
     458             :       /* We do need to check is_builtin_key_or_sysvar here, because pack
     459             :          has not yet loaded the address LUT accounts, so it doesn't
     460             :          reject these yet. */
     461           0 :       int is_writable = !fd_bank_abi_builtin_keys_and_sysvars_tbl_contains( (const fd_acct_addr_t*)(loaded_addresses->writable + i) ) &&
     462           0 :                         (!is_key_called_as_program( txn, (ushort)(txn->acct_addr_cnt+i) ) || _is_upgradeable_loader_present);
     463           0 :       v0->is_writable_account_cache[ txn->acct_addr_cnt+i ] = !!is_writable;
     464           0 :     }
     465           0 :     for( ushort i=0; i<txn->addr_table_adtl_cnt-txn->addr_table_adtl_writable_cnt; i++ ) {
     466           0 :       v0->is_writable_account_cache[ txn->acct_addr_cnt+txn->addr_table_adtl_writable_cnt+i ] = 0;
     467           0 :     }
     468             : 
     469           0 :     out_sidecar += txn->acct_addr_cnt + txn->addr_table_adtl_cnt;
     470           0 :     out_sidecar = (void*)fd_ulong_align_up( (ulong)out_sidecar, 8UL );
     471             : 
     472           0 :     message->account_keys_cnt = txn->acct_addr_cnt;
     473           0 :     message->account_keys_cap = txn->acct_addr_cnt;
     474           0 :     message->account_keys     = (void*)(payload + txn->acct_addr_off);
     475             : 
     476           0 :     message->instructions_cnt = txn->instr_cnt;
     477           0 :     message->instructions_cap = txn->instr_cnt;
     478           0 :     message->instructions     = (void*)out_sidecar;
     479           0 :     for( ulong i=0; i<txn->instr_cnt; i++ ) {
     480           0 :       fd_txn_instr_t * instr = &txn->instr[ i ];
     481           0 :       sanitized_txn_abi_compiled_instruction_t * out_instr = &message->instructions[ i ];
     482             : 
     483           0 :       out_instr->accounts_cnt = instr->acct_cnt;
     484           0 :       out_instr->accounts_cap = instr->acct_cnt;
     485           0 :       out_instr->accounts     = payload + instr->acct_off;
     486             : 
     487           0 :       out_instr->data_cnt = instr->data_sz;
     488           0 :       out_instr->data_cap = instr->data_sz;
     489           0 :       out_instr->data     = payload + instr->data_off;
     490             : 
     491           0 :       out_instr->program_id_index = instr->program_id;
     492           0 :     }
     493           0 :     out_sidecar += txn->instr_cnt*sizeof(sanitized_txn_abi_compiled_instruction_t);
     494             : 
     495           0 :     fd_memcpy( message->recent_blockhash, payload + txn->recent_blockhash_off, 32UL );
     496           0 :     message->header.num_required_signatures        = txn->signature_cnt;
     497           0 :     message->header.num_readonly_signed_accounts   = txn->readonly_signed_cnt;
     498           0 :     message->header.num_readonly_unsigned_accounts = txn->readonly_unsigned_cnt;
     499             : 
     500           0 :     message->address_table_lookups_cnt = txn->addr_table_lookup_cnt;
     501           0 :     message->address_table_lookups_cap = txn->addr_table_lookup_cnt;
     502           0 :     message->address_table_lookups     = (void*)out_sidecar;
     503           0 :     for( ulong i=0; i<txn->addr_table_lookup_cnt; i++ ) {
     504           0 :       fd_txn_acct_addr_lut_t const * lookup = fd_txn_get_address_tables_const( txn ) + i;
     505           0 :       sanitized_txn_abi_v0_message_address_table_lookup_t * out_lookup = &message->address_table_lookups[ i ];
     506             : 
     507           0 :       out_lookup->writable_indexes_cnt = lookup->writable_cnt;
     508           0 :       out_lookup->writable_indexes_cap = lookup->writable_cnt;
     509           0 :       out_lookup->writable_indexes     = payload + lookup->writable_off;
     510             : 
     511           0 :       out_lookup->readonly_indexes_cnt = lookup->readonly_cnt;
     512           0 :       out_lookup->readonly_indexes_cap = lookup->readonly_cnt;
     513           0 :       out_lookup->readonly_indexes     = payload + lookup->readonly_off;
     514             : 
     515           0 :       fd_memcpy( out_lookup->account_key, payload + lookup->addr_off, 32UL );
     516           0 :     }
     517           0 :     out_sidecar += txn->addr_table_lookup_cnt*sizeof(sanitized_txn_abi_v0_message_address_table_lookup_t);
     518             : 
     519           0 :     return FD_BANK_ABI_TXN_INIT_SUCCESS;
     520           0 :   } else {
     521             :     /* A program abort case, unknown transaction version should never make it here. */
     522           0 :     FD_LOG_ERR(( "unknown transaction version %u", txn->transaction_version ));
     523           0 :   }
     524           0 : }

Generated by: LCOV version 1.14