LCOV - code coverage report
Current view: top level - flamenco/events - fd_event_runtime.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 109 0.0 %
Date: 2026-08-15 04:34:25 Functions: 0 1 0.0 %

          Line data    Source code
       1             : #include "fd_event_runtime.h"
       2             : #include "../../disco/events/fd_event_report.h"
       3             : 
       4             : void
       5             : fd_event_runtime_txn_emit( fd_txn_in_t  const * txn_in,
       6             :                            fd_txn_out_t const * txn_out,
       7           0 :                            fd_bank_t    const * bank ) {
       8           0 :   if( FD_LIKELY( !fd_event_tl ) ) return;
       9           0 :   if( FD_UNLIKELY( !txn_in->txn || !bank ) ) return;
      10             : 
      11           0 :   fd_event_runtime_txn_t ev = {0};
      12             : 
      13             :   /* Identity */
      14           0 :   uchar const *    payload = (uchar const *)txn_in->txn->payload;
      15           0 :   fd_txn_t const * txn_d   = TXN( txn_in->txn );
      16           0 :   fd_memcpy( ev.signature, payload + txn_d->signature_off, 64UL );
      17           0 :   fd_memcpy( ev.blockhash,       txn_out->details.blockhash.uc, 32UL );
      18           0 :   fd_memcpy( ev.fec_merkle_root, txn_in->fec_merkle_root,       32UL );
      19           0 :   if( FD_LIKELY( txn_out->accounts.cnt>0UL ) ) {
      20           0 :     fd_memcpy( ev.fee_payer, txn_out->accounts.keys[ 0 ].uc, 32UL );
      21           0 :   }
      22             : 
      23           0 :   ev.bank_seq             = bank->bank_seq;
      24           0 :   ev.slot                 = bank->f.slot;
      25           0 :   ev.epoch                = bank->f.epoch;
      26           0 :   ev.index_in_slot        = txn_in->index_in_slot;
      27           0 :   ev.commit_index_in_slot = txn_out->err.is_committable ? txn_out->details.commit_index_in_slot : 0UL;
      28             : 
      29             :   /* Flags */
      30           0 :   ev.is_simple_vote = !!txn_out->details.is_simple_vote;
      31           0 :   ev.is_bundle      = !!txn_in->bundle.is_bundle;
      32           0 :   ev.is_committable = !!txn_out->err.is_committable;
      33           0 :   ev.is_fees_only   = !!txn_out->err.is_fees_only;
      34             : 
      35             :   /* Errors */
      36           0 :   ev.txn_err       = fd_event_txn_err_from_txn_err( txn_out->err.txn_err );
      37           0 :   int is_instr_err = ( txn_out->err.txn_err==FD_RUNTIME_TXN_ERR_INSTRUCTION_ERROR );
      38           0 :   ev.exec_err      = is_instr_err ? fd_event_exec_err_from_exec_err          ( txn_out->err.exec_err      ) : FD_EVENT_RUNTIME_TXN_EXEC_ERR_SUCCESS;
      39           0 :   ev.exec_err_kind = is_instr_err ? fd_event_exec_err_kind_from_exec_err_kind( txn_out->err.exec_err_kind ) : FD_EVENT_RUNTIME_TXN_EXEC_ERR_KIND_NONE;
      40           0 :   ev.exec_err_idx  = is_instr_err ? txn_out->err.exec_err_idx : UINT_MAX;
      41           0 :   ev.custom_err    = ( is_instr_err && txn_out->err.exec_err==FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR )
      42           0 :                        ? txn_out->err.custom_err : UINT_MAX;
      43             : 
      44             :   /* Compute budget */
      45           0 :   fd_compute_budget_details_t const * cb = &txn_out->details.compute_budget;
      46           0 :   ev.compute_unit_limit              = cb->compute_unit_limit;
      47           0 :   ev.compute_unit_price              = cb->compute_unit_price;
      48           0 :   ev.compute_units_consumed          = (cb->compute_unit_limit > cb->compute_meter)
      49           0 :                                          ? cb->compute_unit_limit - cb->compute_meter : 0UL;
      50           0 :   ev.heap_size                       = cb->heap_size;
      51           0 :   ev.num_builtin_instrs              = cb->num_builtin_instrs;
      52           0 :   ev.num_non_builtin_instrs          = cb->num_non_builtin_instrs;
      53           0 :   ev.loaded_accounts_data_size       = txn_out->details.loaded_accounts_data_size;
      54           0 :   ev.loaded_accounts_data_size_limit = cb->loaded_accounts_data_size_limit;
      55           0 :   ev.accounts_resize_delta           = txn_out->details.accounts_resize_delta;
      56             : 
      57             :   /* Fees */
      58           0 :   ev.execution_fee   = txn_out->details.execution_fee;
      59           0 :   ev.priority_fee    = txn_out->details.priority_fee;
      60           0 :   ev.tips            = txn_out->details.tips;
      61           0 :   ev.signature_count = txn_out->details.signature_count;
      62             : 
      63             :   /* Cost-tracker (non-vote only) */
      64           0 :   if( txn_out->details.txn_cost.type==FD_TXN_COST_TYPE_TRANSACTION ) {
      65           0 :     fd_usage_cost_details_t const * c = &txn_out->details.txn_cost.transaction;
      66           0 :     ev.cost_signature                    = c->signature_cost;
      67           0 :     ev.cost_write_lock                   = c->write_lock_cost;
      68           0 :     ev.cost_data_bytes                   = c->data_bytes_cost;
      69           0 :     ev.cost_programs_execution           = c->programs_execution_cost;
      70           0 :     ev.cost_loaded_accounts_data_size    = c->loaded_accounts_data_size_cost;
      71           0 :     ev.cost_allocated_accounts_data_size = c->allocated_accounts_data_size;
      72           0 :   }
      73             : 
      74             :   /* account_diffs: walk per-txn writable accounts, compare prior vs current */
      75           0 :   ulong diff_cnt = 0UL;
      76           0 :   for( ulong i=0UL; i<txn_out->accounts.cnt; i++ ) {
      77           0 :     if( diff_cnt>=64UL ) break;
      78           0 :     fd_acc_t const * acc = txn_out->accounts.account[ i ];
      79           0 :     if( FD_UNLIKELY( !acc ) ) continue;
      80           0 :     if( !txn_out->accounts.is_writable[ i ] ) continue;
      81             : 
      82           0 :     int changed = ( acc->prior_lamports   != acc->lamports   ) ||
      83           0 :                   ( acc->prior_executable != acc->executable ) ||
      84           0 :                   ( acc->prior_data_len   != acc->data_len   ) ||
      85           0 :                   ( memcmp( acc->prior_owner, acc->owner, 32UL )!=0 );
      86           0 :     if( !changed && acc->prior_data && acc->data &&
      87           0 :         memcmp( acc->prior_data, acc->data, acc->data_len )!=0 ) {
      88           0 :       changed = 1;
      89           0 :     }
      90           0 :     if( !changed ) continue;
      91             : 
      92           0 :     fd_event_runtime_txn_account_diffs_t * d = &ev.account_diffs[ diff_cnt++ ];
      93           0 :     fd_memcpy( d->pubkey,     txn_out->accounts.keys[ i ].uc, 32UL );
      94           0 :     fd_memcpy( d->owner,      acc->owner,                     32UL );
      95           0 :     fd_memcpy( d->prev_owner, acc->prior_owner,               32UL );
      96           0 :     d->lamports      = acc->lamports;
      97           0 :     d->prev_lamports = acc->prior_lamports;
      98           0 :     d->data_sz       = acc->data_len;
      99           0 :     d->prev_data_sz  = acc->prior_data_len;
     100           0 :     d->is_executable   = !!acc->executable;
     101           0 :     d->is_stake_update = !!txn_out->accounts.stake_update[ i ];
     102           0 :     d->is_vote_update  = !!txn_out->accounts.vote_update [ i ];
     103           0 :     d->is_new_vote     = !!txn_out->accounts.new_vote    [ i ];
     104           0 :     d->is_rm_vote      = !!txn_out->accounts.rm_vote     [ i ];
     105           0 :   }
     106           0 :   ev.account_diffs_cnt = diff_cnt;
     107             : 
     108             :   /* writable / readonly account lists */
     109           0 :   ulong w_cnt = 0UL, r_cnt = 0UL;
     110           0 :   for( ulong i=0UL; i<txn_out->accounts.cnt; i++ ) {
     111           0 :     fd_acc_t const * acc = txn_out->accounts.account[ i ];
     112           0 :     if( FD_UNLIKELY( !acc ) ) continue;
     113           0 :     if( txn_out->accounts.is_writable[ i ] ) {
     114           0 :       if( w_cnt<64UL ) fd_memcpy( ev.writable_accounts[ w_cnt++ ], txn_out->accounts.keys[ i ].uc, 32UL );
     115           0 :     } else {
     116           0 :       if( r_cnt<64UL ) fd_memcpy( ev.readonly_accounts[ r_cnt++ ], txn_out->accounts.keys[ i ].uc, 32UL );
     117           0 :     }
     118           0 :   }
     119           0 :   ev.writable_accounts_cnt = w_cnt;
     120           0 :   ev.readonly_accounts_cnt = r_cnt;
     121             : 
     122             :   /* program_ids: walk top-level instructions, dedupe in first-occurrence order */
     123           0 :   ulong p_cnt = 0UL;
     124           0 :   for( ushort ii=0; ii<txn_d->instr_cnt; ii++ ) {
     125           0 :     if( p_cnt>=64UL ) break;
     126           0 :     uchar pid_idx = txn_d->instr[ ii ].program_id;
     127           0 :     if( (ulong)pid_idx>=txn_out->accounts.cnt ) continue;
     128           0 :     uchar const * pid = txn_out->accounts.keys[ pid_idx ].uc;
     129           0 :     int seen = 0;
     130           0 :     for( ulong j=0UL; j<p_cnt; j++ ) {
     131           0 :       if( memcmp( ev.program_ids[ j ], pid, 32UL )==0 ) { seen = 1; break; }
     132           0 :     }
     133           0 :     if( !seen ) fd_memcpy( ev.program_ids[ p_cnt++ ], pid, 32UL );
     134           0 :   }
     135           0 :   ev.program_ids_cnt = p_cnt;
     136             : 
     137           0 :   fd_event_report_runtime_txn( &ev );
     138           0 : }

Generated by: LCOV version 1.14