LCOV - code coverage report
Current view: top level - flamenco/txn - fd_txn_generate.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 78 91 85.7 %
Date: 2026-04-01 06:30:45 Functions: 3 4 75.0 %

          Line data    Source code
       1             : #include "fd_txn_generate.h"
       2             : 
       3             : /* Message header type */
       4             : struct __attribute__((packed)) fd_txn_message_hdr {
       5             :   uchar num_signatures;
       6             :   uchar num_readonly_signatures;
       7             :   uchar num_readonly_unsigned;
       8             : };
       9             : 
      10             : typedef struct fd_txn_message_hdr fd_txn_message_hdr_t;
      11             : 
      12             : static fd_txn_instr_t *
      13             : fd_txn_instr_meta_generate( uchar * out_buf,
      14             :                             uchar program_id,
      15             :                             ushort acct_cnt,
      16             :                             ushort data_sz,
      17             :                             ushort acct_off,
      18          27 :                             ushort data_off ) {
      19          27 :     fd_txn_instr_t * out_instr = (fd_txn_instr_t *) out_buf;
      20          27 :     out_instr->program_id = program_id;
      21          27 :     out_instr->acct_cnt   = acct_cnt;
      22          27 :     out_instr->data_sz    = data_sz;
      23          27 :     out_instr->acct_off   = acct_off;
      24          27 :     out_instr->data_off   = data_off;
      25          27 :     return out_instr;
      26          27 : }
      27             : 
      28             : ulong
      29             : fd_txn_base_generate( uchar out_txn_meta[ static FD_TXN_MAX_SZ ],
      30             :                       uchar out_txn_payload[ static FD_TXN_MTU ],
      31             :                       ulong num_signatures,
      32             :                       fd_txn_accounts_t * accounts,
      33          27 :                       uchar const * opt_recent_blockhash ) {
      34             : 
      35             :   /* Number of signatures cannot exceed 127. */
      36          27 :   FD_TEST(num_signatures <= FD_TXN_SIG_MAX);
      37          27 :   *out_txn_payload = (uchar)num_signatures;
      38             : 
      39             :   /* Fill out txn metadata */
      40          27 :   fd_txn_t * txn_meta             = (fd_txn_t *) out_txn_meta;
      41          27 :   txn_meta->acct_addr_cnt         = accounts->acct_cnt;
      42          27 :   txn_meta->readonly_signed_cnt   = accounts->readonly_signed_cnt;
      43          27 :   txn_meta->readonly_unsigned_cnt = accounts->readonly_unsigned_cnt;
      44             :   /* Number of signatures is encoded as a compact u16 but
      45             :      can always be encoded using 1 byte here. */
      46          27 :   txn_meta->message_off           = (ushort)(num_signatures * FD_TXN_SIGNATURE_SZ  + 1);
      47          27 :   txn_meta->signature_off         = (ushort)1UL;
      48          27 :   txn_meta->instr_cnt             = 0;
      49             : 
      50          27 :   FD_TEST(txn_meta->acct_addr_cnt < FD_TXN_ACCT_ADDR_MAX);
      51          27 :   txn_meta->acct_addr_off        = (ushort)(txn_meta->message_off + (sizeof(fd_txn_message_hdr_t)) + 1);
      52          27 :   txn_meta->recent_blockhash_off = (ushort)(txn_meta->acct_addr_off + (txn_meta->acct_addr_cnt * FD_TXN_ACCT_ADDR_SZ));
      53             : 
      54             :   /* Fill message header in txn payload */
      55          27 :   uchar * write_ptr = out_txn_payload + txn_meta->message_off;
      56          27 :   fd_txn_message_hdr_t msg_header = { .num_signatures = accounts->signature_cnt,
      57          27 :                                       .num_readonly_signatures = accounts->readonly_signed_cnt,
      58          27 :                                       .num_readonly_unsigned   = accounts->readonly_unsigned_cnt };
      59          27 :   memcpy( write_ptr, &msg_header, sizeof(fd_txn_message_hdr_t) ) ;
      60          27 :   write_ptr += sizeof(fd_txn_message_hdr_t);
      61             : 
      62             :   /* Write number of accounts */
      63          27 :   *write_ptr = (uchar)txn_meta->acct_addr_cnt;
      64          27 :   write_ptr += 1;
      65             : 
      66             :   /* Write accounts list to txn payload */
      67          27 :   ulong signers_write_sz = FD_TXN_ACCT_ADDR_SZ * (ulong)(accounts->signature_cnt - accounts->readonly_signed_cnt);
      68          27 :   fd_memcpy( write_ptr, accounts->signers_w, signers_write_sz );
      69          27 :   write_ptr += signers_write_sz;
      70             : 
      71          27 :   fd_memcpy( write_ptr, accounts->signers_r, FD_TXN_ACCT_ADDR_SZ * accounts->readonly_signed_cnt );
      72          27 :   write_ptr += FD_TXN_ACCT_ADDR_SZ * accounts->readonly_signed_cnt;
      73             : 
      74          27 :   ulong non_signers_write_sz = FD_TXN_ACCT_ADDR_SZ * (ulong)(accounts->acct_cnt - accounts->readonly_unsigned_cnt - accounts->signature_cnt);
      75          27 :   fd_memcpy( write_ptr, accounts->non_signers_w, non_signers_write_sz);
      76          27 :   write_ptr += non_signers_write_sz;
      77             : 
      78          27 :   fd_memcpy( write_ptr, accounts->non_signers_r, FD_TXN_ACCT_ADDR_SZ * accounts->readonly_unsigned_cnt );
      79          27 :   write_ptr += FD_TXN_ACCT_ADDR_SZ * accounts->readonly_unsigned_cnt;
      80          27 :   FD_TEST( (ushort)((ulong)write_ptr - (ulong)out_txn_payload) == txn_meta->recent_blockhash_off );
      81             : 
      82             :   /* Write recent blockhash */
      83          27 :   if( FD_LIKELY( opt_recent_blockhash ) ) {
      84          27 :     memcpy( write_ptr, opt_recent_blockhash, FD_TXN_BLOCKHASH_SZ );
      85          27 :   } else {
      86           0 :     memset( write_ptr, 0UL, FD_TXN_BLOCKHASH_SZ );
      87           0 :   }
      88          27 :   write_ptr += FD_TXN_BLOCKHASH_SZ;
      89             : 
      90          27 :   return (ulong)(write_ptr - out_txn_payload);
      91          27 : }
      92             : 
      93             : ulong
      94             : fd_txn_add_instr( uchar * txn_meta_ptr,
      95             :                   uchar out_txn_payload[ static FD_TXN_MTU ],
      96             :                   uchar program_id,
      97             :                   uchar const * accounts,
      98             :                   ulong accounts_sz,
      99             :                   uchar const * instr_buf,
     100          27 :                   ulong instr_buf_sz ) {
     101             : 
     102          27 :   fd_txn_t * txn_meta = (fd_txn_t *) txn_meta_ptr;
     103          27 :   FD_TEST( txn_meta->instr_cnt < FD_TXN_INSTR_MAX );
     104          27 :   FD_TEST( txn_meta->recent_blockhash_off != 0 );
     105             : 
     106          27 :   uchar * instr_start = out_txn_payload + txn_meta->recent_blockhash_off + FD_TXN_BLOCKHASH_SZ;
     107          27 :   txn_meta->instr_cnt++;
     108          27 :   uchar * write_ptr       = instr_start;
     109             : 
     110          27 :   uint compact_instr_cnt_sz = fd_cu16_enc( (ushort)txn_meta->instr_cnt, write_ptr );
     111          27 :   FD_TEST( compact_instr_cnt_sz == 1 );
     112             : 
     113          27 :   write_ptr += compact_instr_cnt_sz;
     114             : 
     115             :   /* Calculate offset of next instruction. */
     116          27 :   if ( FD_UNLIKELY( txn_meta->instr_cnt > 1 ) ) {
     117           0 :     write_ptr = out_txn_payload + txn_meta->instr[txn_meta->instr_cnt-2].data_off + txn_meta->instr[txn_meta->instr_cnt-2].data_sz;
     118           0 :   }
     119             : 
     120          27 :   instr_start = write_ptr;
     121             : 
     122          27 :   *write_ptr = program_id;
     123          27 :   write_ptr += sizeof(uchar);
     124             : 
     125          27 :   uint compact_accts_len_sz = fd_cu16_enc( (ushort)accounts_sz, write_ptr );
     126          27 :   write_ptr += compact_accts_len_sz;
     127             : 
     128          27 :   ushort acct_off = (ushort) (write_ptr - out_txn_payload);
     129          27 :   fd_memcpy( write_ptr, accounts, accounts_sz );
     130          27 :   write_ptr += accounts_sz;
     131             : 
     132          27 :   ushort data_sz = (ushort)instr_buf_sz;
     133          27 :   uint compact_data_len_sz = fd_cu16_enc( data_sz, write_ptr );
     134          27 :   write_ptr += compact_data_len_sz;
     135             : 
     136             :   /* Copy data buffer over */
     137          27 :   ushort data_off = (ushort) (write_ptr - out_txn_payload);
     138          27 :   fd_memcpy( write_ptr, instr_buf, data_sz );
     139          27 :   write_ptr += data_sz;
     140             : 
     141          27 :   (void) fd_txn_instr_meta_generate( (uchar*)&txn_meta->instr[txn_meta->instr_cnt-1],
     142          27 :                                       program_id,
     143          27 :                                       (ushort)accounts_sz,
     144          27 :                                       data_sz, acct_off, data_off );
     145          27 :   return (ulong)(write_ptr - out_txn_payload);
     146          27 : }
     147             : 
     148             : void
     149             : fd_txn_reset_instrs( uchar * txn_meta_ptr,
     150           0 :                      uchar out_txn_payload[ static FD_TXN_MTU ] ) {
     151           0 :   fd_txn_t * txn_meta = (fd_txn_t *)txn_meta_ptr;
     152           0 :   if( FD_UNLIKELY( txn_meta->instr_cnt == 0 ) ) {
     153           0 :     return;
     154           0 :   }
     155             : 
     156           0 :   ulong instr_start   = txn_meta->recent_blockhash_off + FD_TXN_BLOCKHASH_SZ;
     157             : 
     158           0 :   *(out_txn_payload + instr_start) = 0;
     159           0 :   txn_meta->instr_cnt = 0;
     160           0 : }

Generated by: LCOV version 1.14