LCOV - code coverage report
Current view: top level - disco/pack - fd_pack_rebate_sum.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 101 102 99.0 %
Date: 2026-11-10 04:25:15 Functions: 4 4 100.0 %

          Line data    Source code
       1             : #include "fd_pack_rebate_sum.h"
       2             : #include "fd_pack.h"
       3             : #include "../../util/fd_hash32.h"
       4             : #if FD_HAS_AVX
       5             : #include "../../util/simd/fd_avx.h"
       6             : #endif
       7             : 
       8             : static const fd_acct_addr_t null_addr = { 0 };
       9             : 
      10             : #define MAP_NAME        rmap
      11        5346 : #define MAP_T           fd_pack_rebate_entry_t
      12          87 : #define MAP_LG_SLOT_CNT 13
      13        7774 : #define MAP_KEY_T       fd_acct_addr_t
      14      715071 : #define MAP_KEY_NULL    null_addr
      15             : #if FD_HAS_AVX
      16        7774 : # define MAP_KEY_INVAL(k)      _mm256_testz_si256( wb_ldu( (k).b ), wb_ldu( (k).b ) )
      17             : #else
      18             : # define MAP_KEY_INVAL(k)      MAP_KEY_EQUAL(k, null_addr)
      19             : #endif
      20        2832 : #define MAP_KEY_EQUAL(k0,k1)   (!memcmp((k0).b,(k1).b, FD_TXN_ACCT_ADDR_SZ))
      21             : #define MAP_KEY_EQUAL_IS_SLOW  1
      22             : #define MAP_MEMOIZE            0
      23        5257 : #define MAP_KEY_HASH(key,seed) ((uint)fd_hash32( (key).b, (seed) ))
      24           0 : #define MAP_MOVE(d,s)          (__extension__({ FD_LOG_CRIT(( "Tried to move a map value" )); (d)=(s); }))
      25             : 
      26             : #include "../../util/tmpl/fd_map_dynamic.c"
      27             : 
      28             : FD_STATIC_ASSERT( (1UL<<MAP_LG_SLOT_CNT)==8192UL, map_slot_cnt );
      29             : 
      30             : void *
      31             : fd_pack_rebate_sum_new( void * mem,
      32          87 :                         ulong  seed ) {
      33          87 :   fd_pack_rebate_sum_t * s = (fd_pack_rebate_sum_t *)mem;
      34             : 
      35          87 :   s->total_cost_rebate        = 0UL;
      36          87 :   s->data_bytes_rebate        = 0UL;
      37          87 :   s->microblock_cnt_rebate    = 0UL;
      38          87 :   s->alloc_rebate             = 0UL;
      39          87 :   s->ib_result                = 0;
      40          87 :   s->writer_cnt               = 0U;
      41             : 
      42          87 :   s->map = rmap_join( rmap_new( s->map_mem, MAP_LG_SLOT_CNT, seed ) );
      43          87 :   FD_TEST( s->map );
      44             : 
      45             :   /* Not a good place to put this, but there's not really a better place
      46             :      for it either.  The compiler should eliminate it. */
      47          87 :   FD_TEST( rmap_align()==FD_PACK_REBATE_SUM_MAP_ALIGN );
      48          87 :   FD_TEST( rmap_footprint( MAP_LG_SLOT_CNT )==FD_PACK_REBATE_SUM_MAP_FOOTPRINT );
      49          87 :   return mem;
      50          87 : }
      51             : 
      52             : 
      53         204 : #define HEADROOM (FD_PACK_REBATE_SUM_CAPACITY-FD_PACK_REBATE_MAX_ENTRIES)
      54             : 
      55             : ulong
      56             : fd_pack_rebate_sum_add_txn( fd_pack_rebate_sum_t         * s,
      57             :                             fd_txn_p_t     const         * txns,
      58             :                             fd_acct_addr_t const * const * adtl_writable,
      59         204 :                             ulong                          txn_cnt ) {
      60             :   /* See end of function for this equation */
      61         204 :   if( FD_UNLIKELY( txn_cnt==0UL ) ) return (ulong)((fd_int_max( 0, (int)s->writer_cnt - (int)HEADROOM ) + (int)FD_PACK_REBATE_MAX_ENTRIES-1) / (int)FD_PACK_REBATE_MAX_ENTRIES);
      62             : 
      63         201 :   int is_initializer_bundle = 1;
      64         201 :   int ib_success            = 1;
      65         201 :   int any_in_block          = 0;
      66             : 
      67         528 :   for( ulong i=0UL; i<txn_cnt; i++ ) {
      68         327 :     fd_txn_p_t const * txn = txns+i;
      69         327 :     ulong rebated_cus   = txn->execle_cu.rebated_cus;
      70         327 :     int   in_block      = !!(txn->flags & FD_TXN_P_FLAGS_EXECUTE_SUCCESS);
      71             : 
      72             :     /* For IB purposes, treat AlreadyProcessed (7) as success.  If one
      73             :        transaction is an initializer bundle, they all must be, so it's
      74             :        unclear if the first line should be an |= or an &=, but &= seems
      75             :        more right. */
      76         327 :     is_initializer_bundle &= !!(txn->flags & FD_TXN_P_FLAGS_INITIALIZER_BUNDLE);
      77         327 :     ib_success            &= in_block | ((txn->flags&FD_TXN_P_FLAGS_RESULT_MASK)==(7U<<24));
      78         327 :     any_in_block          |= in_block;
      79             : 
      80         327 :     s->total_cost_rebate += rebated_cus;
      81         327 :     s->data_bytes_rebate += fd_ulong_if( !in_block,                                  txn->payload_sz, 0UL );
      82         327 :     s->alloc_rebate      += fd_ulong_if( !in_block,                                  txn->pack_alloc, 0UL );
      83             : 
      84         327 :     if( FD_UNLIKELY( rebated_cus==0UL ) ) continue;
      85             : 
      86         324 :     fd_acct_addr_t const * accts = fd_txn_get_acct_addrs( TXN(txn), txn->payload );
      87         324 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( TXN(txn), FD_TXN_ACCT_CAT_WRITABLE & FD_TXN_ACCT_CAT_IMM );
      88         858 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
      89             : 
      90         534 :       ulong j=fd_txn_acct_iter_idx( iter );
      91             : 
      92         534 :       fd_pack_rebate_entry_t * in_table = rmap_query( s->map, accts[j], NULL );
      93         534 :       if( FD_UNLIKELY( !in_table ) ) {
      94         354 :         in_table = rmap_insert( s->map, accts[j] );
      95         354 :         in_table->rebate_cus = 0UL;
      96         354 :         s->inserted[ s->writer_cnt++ ] = in_table;
      97         354 :       }
      98         534 :       in_table->rebate_cus += rebated_cus;
      99         534 :     }
     100             :     /* ALT accounts are pre-resolved by resolv_tile and passed via
     101             :        fd_txn_e_t, so we always rebate even if bank sanitization
     102             :        failed (e.g. due to LUT deactivation).  If adtl_writable[i] is
     103             :        NULL, we do not rebate ALT accounts. */
     104         324 :     accts = adtl_writable[i];
     105         324 :     if( FD_LIKELY( accts ) ) {
     106        2466 :       for( ulong j=0UL; j<(ulong)TXN(txn)->addr_table_adtl_writable_cnt; j++ ) {
     107        2148 :         fd_pack_rebate_entry_t * in_table = rmap_query( s->map, accts[j], NULL );
     108        2148 :         if( FD_UNLIKELY( !in_table ) ) {
     109        2136 :           in_table = rmap_insert( s->map, accts[j] );
     110        2136 :           in_table->rebate_cus = 0UL;
     111        2136 :           s->inserted[ s->writer_cnt++ ] = in_table;
     112        2136 :         }
     113        2148 :         in_table->rebate_cus += rebated_cus;
     114        2148 :       }
     115         318 :     }
     116         324 :     FD_TEST( s->writer_cnt<=FD_PACK_REBATE_SUM_CAPACITY );
     117         324 :   }
     118             : 
     119         201 :   int is_bundle = txns->flags & FD_TXN_P_FLAGS_BUNDLE; /* can't mix bundle and non-bundle */
     120         201 :   ulong microblock_cnt_rebate = fd_ulong_if( any_in_block, 0UL, fd_ulong_if( is_bundle, txn_cnt, 1UL ) );
     121         201 :   s->microblock_cnt_rebate += microblock_cnt_rebate;
     122         201 :   s->data_bytes_rebate     += microblock_cnt_rebate*48UL; /* microblock headers */
     123             : 
     124         201 :   if( FD_UNLIKELY( is_initializer_bundle & (s->ib_result!=-1) ) ) { /* if in -1 state, stay. Shouldn't be possible */
     125           9 :     s->ib_result = fd_int_if( ib_success, 1, -1 );
     126           9 :   }
     127             : 
     128             :   /* We want to make sure that we have enough capacity to insert
     129             :      FD_PACK_REBATE_MAX_ENTRIES addresses without hitting
     130             :      FD_PACK_REBATE_SUM_CAPACITY.  Thus, if x is the current value of
     131             :      writer_cnt, we need to call report at least y times to ensure
     132             :                         x-y*FD_PACK_REBATE_MAX_ENTRIES <= HEADROOM
     133             :                                y >= (x-HEADROOM)/FD_PACK_REBATE_MAX_ENTRIES
     134             :      but y is an integer, so
     135             :      y >= ceiling( (x-HEADROOM)/FD_PACK_REBATE_MAX_ENTRIES ) */
     136         201 :   return (ulong)((fd_int_max( 0, (int)s->writer_cnt - (int)HEADROOM ) + (int)FD_PACK_REBATE_MAX_ENTRIES-1) / (int)FD_PACK_REBATE_MAX_ENTRIES);
     137         201 : }
     138             : 
     139             : 
     140             : ulong
     141             : fd_pack_rebate_sum_report( fd_pack_rebate_sum_t * s,
     142          72 :                            fd_pack_rebate_t     * out ) {
     143          72 :   if( FD_UNLIKELY( (s->ib_result==0) & (s->total_cost_rebate==0UL) & (s->writer_cnt==0U) ) ) return 0UL;
     144          60 :   out->total_cost_rebate       = s->total_cost_rebate;          s->total_cost_rebate       = 0UL;
     145          60 :   out->data_bytes_rebate       = s->data_bytes_rebate;          s->data_bytes_rebate       = 0UL;
     146          60 :   out->microblock_cnt_rebate   = s->microblock_cnt_rebate;      s->microblock_cnt_rebate   = 0UL;
     147          60 :   out->alloc_rebate            = s->alloc_rebate;               s->alloc_rebate            = 0UL;
     148          60 :   out->ib_result               = s->ib_result;                  s->ib_result               = 0;
     149             : 
     150          60 :   out->writer_cnt = 0U;
     151          60 :   ulong writer_cnt = fd_ulong_min( s->writer_cnt, FD_PACK_REBATE_MAX_ENTRIES );
     152        2229 :   for( ulong i=0UL; i<writer_cnt; i++ ) {
     153        2169 :     fd_pack_rebate_entry_t * e = s->inserted[ --(s->writer_cnt) ];
     154        2169 :     out->writer_rebates[ out->writer_cnt++ ] = *e;
     155        2169 :     rmap_remove( s->map, e );
     156        2169 :   }
     157             : 
     158          60 :   return sizeof(*out)-sizeof(fd_pack_rebate_entry_t)+(out->writer_cnt)*sizeof(fd_pack_rebate_entry_t);
     159          72 : }
     160             : 
     161             : void
     162          84 : fd_pack_rebate_sum_clear( fd_pack_rebate_sum_t * s ) {
     163          84 :   s->total_cost_rebate       = 0UL;
     164          84 :   s->data_bytes_rebate       = 0UL;
     165          84 :   s->microblock_cnt_rebate   = 0UL;
     166          84 :   s->alloc_rebate            = 0UL;
     167          84 :   s->ib_result               = 0;
     168             : 
     169          84 :   ulong writer_cnt = s->writer_cnt;
     170         282 :   for( ulong i=0UL; i<writer_cnt; i++ ) {
     171         198 :     fd_pack_rebate_entry_t * e = s->inserted[ --(s->writer_cnt) ];
     172         198 :     rmap_remove( s->map, e );
     173         198 :   }
     174          84 : }

Generated by: LCOV version 1.14