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

Generated by: LCOV version 1.14