LCOV - code coverage report
Current view: top level - discof/rpcserver - fd_rpc_history.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 333 0.0 %
Date: 2025-10-13 04:42:14 Functions: 0 18 0.0 %

          Line data    Source code
       1             : #include "fd_rpc_history.h"
       2             : #include <unistd.h>
       3             : #include <fcntl.h>
       4             : 
       5             : #include "../../ballet/block/fd_microblock.h"
       6             : #include "../../flamenco/runtime/fd_system_ids.h"
       7             : 
       8             : #include <string.h>
       9             : 
      10             : struct fd_rpc_block {
      11             :   ulong slot;
      12             :   ulong next;
      13             :   fd_replay_slot_completed_t info;
      14             :   ulong file_offset;
      15             :   ulong file_size;
      16             : };
      17             : 
      18             : typedef struct fd_rpc_block fd_rpc_block_t;
      19             : 
      20             : #define MAP_NAME              fd_rpc_block_map
      21           0 : #define MAP_T                 fd_rpc_block_t
      22             : #define MAP_KEY_T             ulong
      23           0 : #define MAP_KEY               slot
      24           0 : #define MAP_KEY_EQ(k0,k1)     ((*k0)==(*k1))
      25           0 : #define MAP_KEY_HASH(key,seed) fd_ulong_hash(*key ^ seed)
      26             : #include "../../util/tmpl/fd_map_giant.c"
      27             : 
      28             : struct fd_rpc_txn {
      29             :   fd_rpc_txn_key_t sig;
      30             :   ulong next;
      31             :   ulong slot;
      32             :   ulong file_offset;
      33             :   ulong file_size;
      34             :   struct fd_rpc_txn * next_lru;
      35             : };
      36             : typedef struct fd_rpc_txn fd_rpc_txn_t;
      37             : 
      38             : FD_FN_PURE int
      39           0 : fd_rpc_txn_key_equal( fd_rpc_txn_key_t const * k0, fd_rpc_txn_key_t const * k1 ) {
      40           0 :   for( ulong i = 0; i < FD_ED25519_SIG_SZ / sizeof( ulong ); ++i )
      41           0 :     if( k0->v[i] != k1->v[i] ) return 0;
      42           0 :   return 1;
      43           0 : }
      44             : 
      45             : FD_FN_PURE ulong
      46           0 : fd_rpc_txn_key_hash( fd_rpc_txn_key_t const * k, ulong seed ) {
      47           0 :   ulong h = seed;
      48           0 :   for( ulong i = 0; i < FD_ED25519_SIG_SZ / sizeof( ulong ); ++i )
      49           0 :     h ^= k->v[i];
      50           0 :   return h;
      51           0 : }
      52             : 
      53             : #define MAP_NAME              fd_rpc_txn_map
      54           0 : #define MAP_T                 fd_rpc_txn_t
      55           0 : #define MAP_KEY               sig
      56             : #define MAP_KEY_T             fd_rpc_txn_key_t
      57           0 : #define MAP_KEY_EQ(k0,k1)     fd_rpc_txn_key_equal(k0,k1)
      58           0 : #define MAP_KEY_HASH(key,seed) fd_rpc_txn_key_hash(key,seed)
      59             : #include "../../util/tmpl/fd_map_giant.c"
      60             : 
      61             : struct fd_rpc_acct_map_elem {
      62             :   fd_pubkey_t key;
      63             :   ulong next;
      64             :   ulong slot;
      65             :   fd_rpc_txn_key_t sig; /* Transaction signature */
      66             :   struct fd_rpc_acct_map_elem * next_lru;
      67             : };
      68             : typedef struct fd_rpc_acct_map_elem fd_rpc_acct_map_elem_t;
      69             : #define MAP_NAME fd_rpc_acct_map
      70             : #define MAP_KEY_T fd_pubkey_t
      71           0 : #define MAP_ELE_T fd_rpc_acct_map_elem_t
      72           0 : #define MAP_KEY_HASH(key,seed) fd_hash( seed, key, sizeof(fd_pubkey_t) )
      73           0 : #define MAP_KEY_EQ(k0,k1)      fd_pubkey_eq( k0, k1 )
      74             : #define MAP_MULTI 1
      75             : #include "../../util/tmpl/fd_map_chain.c"
      76             : #define POOL_NAME fd_rpc_acct_map_pool
      77           0 : #define POOL_T    fd_rpc_acct_map_elem_t
      78             : #include "../../util/tmpl/fd_pool.c"
      79             : 
      80           0 : #define FD_REASM_MAP_COL_CNT (1UL<<10)
      81             : #define FD_REASM_MAP_COL_HEIGHT (128UL)
      82             : struct fd_rpc_reasm_map {
      83             :   struct fd_rpc_reasm_map_column {
      84             :     ulong ele_cnt;  /* The number of shreds received in this column */    uchar end_found; /* Whether the last slice of the slot has been found */
      85             :     fd_reasm_fec_t ele[FD_REASM_MAP_COL_HEIGHT];
      86             :   } cols[FD_REASM_MAP_COL_CNT];
      87             :   ulong head; /* Next open column */
      88             :   ulong tail; /* Oldest column */
      89             : };
      90             : typedef struct fd_rpc_reasm_map fd_rpc_reasm_map_t;
      91             : 
      92             : struct fd_rpc_history {
      93             :   fd_spad_t * spad;
      94             :   fd_rpc_block_t * block_map;
      95             :   ulong block_cnt;
      96             :   fd_rpc_txn_t * txn_map;
      97             :   fd_rpc_txn_t * txn_oldest_lru;
      98             :   fd_rpc_txn_t * txn_newest_lru;
      99             :   fd_rpc_acct_map_t * acct_map;
     100             :   fd_rpc_acct_map_elem_t * acct_pool;
     101             :   fd_rpc_acct_map_elem_t * acct_oldest_lru;
     102             :   fd_rpc_acct_map_elem_t * acct_newest_lru;
     103             :   fd_rpc_reasm_map_t * reasm_map;
     104             :   ulong first_slot;
     105             :   ulong latest_slot;
     106             :   int file_fd;
     107             :   ulong file_totsz;
     108             :   int include_votes;
     109             : };
     110             : 
     111             : fd_rpc_history_t *
     112           0 : fd_rpc_history_create(fd_rpcserver_args_t * args) {
     113           0 :   fd_spad_t * spad = args->spad;
     114           0 :   fd_rpc_history_t * hist = (fd_rpc_history_t *)fd_spad_alloc( spad, alignof(fd_rpc_history_t), sizeof(fd_rpc_history_t) );
     115           0 :   memset(hist, 0, sizeof(fd_rpc_history_t));
     116           0 :   hist->spad = spad;
     117             : 
     118           0 :   hist->first_slot = ULONG_MAX;
     119           0 :   hist->latest_slot = 0;
     120             : 
     121           0 :   hist->block_map = fd_rpc_block_map_join( fd_rpc_block_map_new( fd_spad_alloc( spad, fd_rpc_block_map_align(), fd_rpc_block_map_footprint(args->block_index_max) ), args->block_index_max, 0 ) );
     122             : 
     123           0 :   hist->txn_map = fd_rpc_txn_map_join( fd_rpc_txn_map_new( fd_spad_alloc( spad, fd_rpc_txn_map_align(), fd_rpc_txn_map_footprint(args->txn_index_max) ), args->txn_index_max, 0 ) );
     124             : 
     125           0 :   void * mem = fd_spad_alloc( spad, fd_rpc_acct_map_align(), fd_rpc_acct_map_footprint( args->acct_index_max/2 ) );
     126           0 :   hist->acct_map = fd_rpc_acct_map_join( fd_rpc_acct_map_new( mem, args->acct_index_max/2, 0 ) );
     127           0 :   mem = fd_spad_alloc( spad, fd_rpc_acct_map_pool_align(), fd_rpc_acct_map_pool_footprint( args->acct_index_max ) );
     128           0 :   hist->acct_pool = fd_rpc_acct_map_pool_join( fd_rpc_acct_map_pool_new( mem, args->acct_index_max ) );
     129             : 
     130           0 :   mem = fd_spad_alloc( spad, alignof(fd_rpc_reasm_map_t), sizeof(fd_rpc_reasm_map_t) );
     131           0 :   memset(mem, 0, sizeof(fd_rpc_reasm_map_t));
     132           0 :   hist->reasm_map = (fd_rpc_reasm_map_t *)mem;
     133             : 
     134           0 :   hist->file_fd = open( args->history_file, O_CREAT | O_RDWR | O_TRUNC, 0644 );
     135           0 :   if( hist->file_fd == -1 ) FD_LOG_ERR(( "unable to open rpc history file: %s", args->history_file ));
     136           0 :   hist->file_totsz = 0;
     137             : 
     138           0 :   hist->include_votes = args->include_votes;
     139             : 
     140           0 :   return hist;
     141           0 : }
     142             : 
     143             : static fd_rpc_block_t *
     144           0 : fd_rpc_history_alloc_block(fd_rpc_history_t * hist, ulong slot) {
     145           0 :   fd_rpc_block_t * blk = fd_rpc_block_map_query(hist->block_map, &slot, NULL);
     146           0 :   if( blk ) return blk;
     147           0 :   if( fd_rpc_block_map_is_full( hist->block_map ) ) return NULL; /* Out of space */
     148           0 :   blk = fd_rpc_block_map_insert( hist->block_map, &slot );
     149           0 :   if( blk == NULL ) {
     150           0 :     FD_LOG_ERR(( "unable to save slot %lu block", slot ));
     151           0 :     return NULL;
     152           0 :   }
     153           0 :   blk->slot = slot;
     154           0 :   blk->file_offset = 0UL;
     155           0 :   blk->file_size = 0UL;
     156           0 :   memset( &blk->info, 0, sizeof(fd_replay_slot_completed_t) );
     157           0 :   blk->info.slot = slot;
     158           0 :   if( hist->first_slot == ULONG_MAX ) {
     159           0 :     hist->first_slot = hist->latest_slot = slot;
     160           0 :   } else {
     161           0 :     if( slot < hist->first_slot ) hist->first_slot = slot;
     162           0 :     else if( slot > hist->latest_slot ) hist->latest_slot = slot;
     163           0 :   }
     164           0 :   hist->block_cnt++;
     165           0 :   return blk;
     166           0 : }
     167             : 
     168             : void
     169           0 : fd_rpc_history_debug(fd_rpc_history_t * hist) {
     170           0 :   fd_rpc_reasm_map_t * reasm_map = hist->reasm_map;
     171           0 :   ulong tot_cnt = 0;
     172           0 :   for( ulong slot = reasm_map->tail; slot < reasm_map->head; slot++ ) {
     173           0 :     ulong col_idx = slot & (FD_REASM_MAP_COL_CNT - 1);
     174           0 :     struct fd_rpc_reasm_map_column * col = &reasm_map->cols[col_idx];
     175           0 :     FD_LOG_NOTICE(( "slot %lu: %lu fecs", slot, col->ele_cnt ));
     176           0 :     tot_cnt += col->ele_cnt;
     177           0 :   }
     178           0 :   FD_LOG_NOTICE(( "%lu head, %lu tail, %lu total fecs, %lu total blocks",
     179           0 :                   reasm_map->head, reasm_map->tail, tot_cnt, reasm_map->head - reasm_map->tail ));
     180           0 : }
     181             : 
     182             : void
     183           0 : fd_rpc_history_save_info(fd_rpc_history_t * hist, fd_replay_slot_completed_t * info) {
     184           0 :   fd_rpc_block_t * blk = fd_rpc_history_alloc_block( hist, info->slot );
     185           0 :   if( blk == NULL ) return;
     186           0 :   blk->info = *info;
     187           0 : }
     188             : 
     189             : static ulong
     190           0 : fd_rpc_history_scan_block(fd_rpc_history_t * hist, ulong slot, ulong file_offset, uchar * blk_data, ulong blk_sz) {
     191           0 :   ulong blockoff = 0;
     192           0 :   ulong ret = 0;
     193           0 :   while (blockoff < blk_sz) {
     194           0 :     if ( blockoff + sizeof(ulong) > blk_sz )
     195           0 :       return ret;
     196           0 :     ulong mcount = *(const ulong *)(blk_data + blockoff);
     197           0 :     blockoff += sizeof(ulong);
     198             : 
     199             :     /* Loop across microblocks */
     200           0 :     for (ulong mblk = 0; mblk < mcount; ++mblk) {
     201           0 :       if ( blockoff + sizeof(fd_microblock_hdr_t) > blk_sz ) {
     202           0 :         FD_LOG_ERR(("premature end of block"));
     203           0 :         return ret;
     204           0 :       }
     205           0 :       fd_microblock_hdr_t * hdr = (fd_microblock_hdr_t *)((const uchar *)blk_data + blockoff);
     206           0 :       blockoff += sizeof(fd_microblock_hdr_t);
     207             : 
     208             :       /* Loop across transactions */
     209           0 :       for ( ulong txn_idx = 0; txn_idx < hdr->txn_cnt; txn_idx++ ) {
     210           0 :         uchar txn_out[FD_TXN_MAX_SZ];
     211           0 :         ulong pay_sz = 0;
     212           0 :         const uchar* raw = (const uchar *)blk_data + blockoff;
     213           0 :         ulong txn_sz = fd_txn_parse_core(raw, fd_ulong_min(blk_sz - blockoff, FD_TXN_MTU), txn_out, NULL, &pay_sz);
     214           0 :         if ( txn_sz == 0 || txn_sz > FD_TXN_MAX_SZ ) {
     215           0 :           FD_LOG_ERR( ( "failed to parse transaction %lu in microblock %lu (%lu) at offset %lu", txn_idx, mblk, ret,blockoff ) );
     216           0 :           return ret;
     217           0 :         }
     218           0 :         fd_txn_t * txn = (fd_txn_t *)txn_out;
     219             : 
     220           0 :         fd_pubkey_t * accs = (fd_pubkey_t *)((uchar *)raw + txn->acct_addr_off);
     221           0 :         if( !hist->include_votes ) {
     222           0 :           int skip_txn = 0;
     223           0 :           for( ulong i = 0UL; i < txn->acct_addr_cnt; i++ ) {
     224           0 :             if( !memcmp(&accs[i], fd_solana_vote_program_id.key, sizeof(fd_pubkey_t)) ) {
     225           0 :               skip_txn = 1;
     226           0 :               break;
     227           0 :             }
     228           0 :           }
     229           0 :           if( skip_txn ) {
     230           0 :             blockoff += pay_sz;
     231           0 :             continue;
     232           0 :           }
     233           0 :         }
     234             : 
     235             :         /* Loop across signatures */
     236           0 :         fd_ed25519_sig_t const * sigs = (fd_ed25519_sig_t const *)(raw + txn->signature_off);
     237           0 :         for ( uchar j = 0; j < txn->signature_cnt; j++ ) {
     238           0 :           while( fd_rpc_txn_map_is_full( hist->txn_map ) ) {
     239             :             /* Remove the oldest entry from the map */
     240           0 :             fd_rpc_txn_t * ent = hist->txn_oldest_lru;
     241           0 :             hist->txn_oldest_lru = ent->next_lru;
     242           0 :             fd_rpc_txn_map_remove( hist->txn_map, &ent->sig );
     243           0 :           }
     244             : 
     245             :           /* Insert the new entry into the map */
     246           0 :           fd_rpc_txn_key_t key;
     247           0 :           memcpy(&key, (const uchar*)&sigs[j], sizeof(key));
     248           0 :           fd_rpc_txn_t * ent = fd_rpc_txn_map_insert( hist->txn_map, &key );
     249           0 :           ent->file_offset = file_offset + blockoff;
     250           0 :           ent->file_size = pay_sz;
     251           0 :           ent->slot = slot;
     252             : 
     253             :           /* Update the LRU chain*/
     254           0 :           ent->next_lru = NULL;
     255           0 :           if( hist->txn_newest_lru ) {
     256           0 :             hist->txn_newest_lru->next_lru = ent;
     257           0 :             hist->txn_newest_lru = ent;
     258           0 :           } else {
     259           0 :             hist->txn_newest_lru = ent;
     260           0 :             hist->txn_oldest_lru = ent;
     261           0 :           }
     262           0 :         }
     263             : 
     264             :         /* Loop across accounts */
     265           0 :         fd_rpc_txn_key_t sig0;
     266           0 :         memcpy(&sig0, (const uchar*)sigs, sizeof(sig0));
     267           0 :         for( ulong i = 0UL; i < txn->acct_addr_cnt; i++ ) {
     268           0 :           if( !memcmp(&accs[i], fd_solana_vote_program_id.key, sizeof(fd_pubkey_t)) ) continue; /* Ignore votes */
     269             : 
     270           0 :           while( !fd_rpc_acct_map_pool_free( hist->acct_pool ) ) {
     271             :             /* Remove the oldest entry from the map */
     272           0 :             fd_rpc_acct_map_elem_t * ent = hist->acct_oldest_lru;
     273           0 :             hist->acct_oldest_lru = ent->next_lru;
     274           0 :             ent = fd_rpc_acct_map_ele_remove( hist->acct_map, &ent->key, NULL, hist->acct_pool );
     275           0 :             if( ent ) fd_rpc_acct_map_pool_ele_release( hist->acct_pool, ent );
     276           0 :           }
     277             : 
     278             :           /* Insert the new entry into the map */
     279           0 :           fd_rpc_acct_map_elem_t * ele = fd_rpc_acct_map_pool_ele_acquire( hist->acct_pool );
     280           0 :           ele->key = accs[i];
     281           0 :           ele->slot = slot;
     282           0 :           ele->sig = sig0;
     283           0 :           fd_rpc_acct_map_ele_insert( hist->acct_map, ele, hist->acct_pool );
     284             : 
     285             :           /* Update the LRU chain */
     286           0 :           ele->next_lru = NULL;
     287           0 :           if( hist->acct_newest_lru ) {
     288           0 :             hist->acct_newest_lru->next_lru = ele;
     289           0 :             hist->acct_newest_lru = ele;
     290           0 :           } else {
     291           0 :             hist->acct_newest_lru = ele;
     292           0 :             hist->acct_oldest_lru = ele;
     293           0 :           }
     294           0 :         }
     295             : 
     296           0 :         blockoff += pay_sz;
     297           0 :       }
     298           0 :     }
     299           0 :     ret = blockoff;
     300           0 :   }
     301           0 :   return ret;
     302           0 : }
     303             : 
     304             : void
     305           0 : fd_rpc_history_process_column(fd_rpc_history_t * hist, struct fd_rpc_reasm_map_column * col, fd_store_t * store, fd_reasm_fec_t * fec) {
     306           0 :   ulong slot = fec->slot;
     307             : 
     308             :   /* Get a block from the map */
     309           0 :   fd_rpc_block_t * blk = fd_rpc_history_alloc_block( hist, slot );
     310           0 :   if( blk == NULL ) return;
     311           0 :   ulong file_offset = blk->file_offset = hist->file_totsz;
     312           0 :   blk->file_size = 0;
     313             : 
     314             :   /* Look up all the store_fec_t elements for this column */
     315           0 :   fd_store_fec_t * list[FD_REASM_MAP_COL_HEIGHT];
     316           0 :   for( ulong idx = 0; idx < col->ele_cnt; ) {
     317           0 :     ulong end_idx = ULONG_MAX;
     318           0 :     FD_SPAD_FRAME_BEGIN( hist->spad ) {
     319             :       /* Query the next batch */
     320           0 :       fd_store_shacq( store );
     321           0 :       ulong batch_sz = 0;
     322           0 :       for( ulong i = idx; i < col->ele_cnt; i++ ) {
     323           0 :         fd_reasm_fec_t * ele = &col->ele[i];
     324           0 :         fd_store_fec_t * fec_p = list[i-idx] = fd_store_query( store, &ele->key );
     325           0 :         if( !fec_p ) {
     326           0 :           fd_store_shrel( store );
     327           0 :           FD_LOG_WARNING(( "missing fec when assembling block %lu", slot ));
     328           0 :           return;
     329           0 :         }
     330           0 :         batch_sz += fec_p->data_sz;
     331           0 :         if( col->ele[i].data_complete ) {
     332           0 :           end_idx = i;
     333           0 :           break;
     334           0 :         }
     335           0 :       }
     336           0 :       if( end_idx == ULONG_MAX ) {
     337           0 :         fd_store_shrel( store );
     338           0 :         FD_LOG_ERR(( "missing data complete flag" ));
     339           0 :         return;
     340           0 :       }
     341           0 :       uchar * blk_data = fd_spad_alloc( hist->spad, alignof(ulong), batch_sz );
     342           0 :       ulong batch_off = 0;
     343           0 :       for( ulong i = idx; i <= end_idx; i++ ) {
     344           0 :         fd_store_fec_t * fec_p = list[i-idx];
     345           0 :         fd_memcpy( blk_data + batch_off, fec_p->data, fec_p->data_sz );
     346           0 :         batch_off += fec_p->data_sz;
     347           0 :       }
     348           0 :       FD_TEST( batch_off == batch_sz );
     349           0 :       fd_store_shrel( store );
     350             :       /* Scan the block. Trim the padding. */
     351           0 :       batch_sz = fd_rpc_history_scan_block( hist, slot, file_offset, blk_data, batch_sz );
     352             :       /* Write the trimmed batch to the file */
     353           0 :       if( pwrite( hist->file_fd, blk_data, batch_sz, (long)file_offset ) != (ssize_t)batch_sz ) {
     354           0 :         FD_LOG_ERR(( "unable to write to rpc history file" ));
     355           0 :         return;
     356           0 :       }
     357           0 :       file_offset += batch_sz;
     358           0 :       blk->file_size += batch_sz;
     359           0 :       hist->file_totsz = file_offset;
     360           0 :     } FD_SPAD_FRAME_END;
     361           0 :     idx = end_idx + 1;
     362           0 :   }
     363             : 
     364           0 :   FD_LOG_NOTICE(( "processed slot %lu", slot ));
     365           0 : }
     366             : 
     367             : static void
     368           0 : fd_rpc_history_discard_column(fd_rpc_reasm_map_t * reasm_map, ulong slot) {
     369           0 :   ulong col_idx = slot & (FD_REASM_MAP_COL_CNT - 1);
     370           0 :   struct fd_rpc_reasm_map_column * col = &reasm_map->cols[col_idx];
     371           0 :   col->ele_cnt = 0;
     372           0 : }
     373             : 
     374             : void
     375           0 : fd_rpc_history_save_fec(fd_rpc_history_t * hist, fd_store_t * store, fd_reasm_fec_t * fec_msg ) {
     376           0 :   fd_rpc_reasm_map_t * reasm_map = hist->reasm_map;
     377             : 
     378           0 :   if( reasm_map->head == 0UL ) {
     379           0 :     reasm_map->head = fec_msg->slot+1;
     380           0 :     reasm_map->tail = fec_msg->slot;
     381           0 :   }
     382           0 :   if( fec_msg->slot < reasm_map->tail ) return; /* Do not go backwards */
     383           0 :   while( fec_msg->slot >= reasm_map->tail + FD_REASM_MAP_COL_CNT ) {
     384           0 :     FD_TEST( reasm_map->tail < reasm_map->head );
     385           0 :     fd_rpc_history_discard_column( reasm_map, reasm_map->tail++ );
     386           0 :   }
     387           0 :   while( fec_msg->slot >= reasm_map->head ) {
     388           0 :     ulong col_idx = (reasm_map->head++) & (FD_REASM_MAP_COL_CNT - 1);
     389           0 :     struct fd_rpc_reasm_map_column * col = &reasm_map->cols[col_idx];
     390           0 :     col->ele_cnt = 0;
     391           0 :   }
     392           0 :   FD_TEST( fec_msg->slot >= reasm_map->tail && fec_msg->slot < reasm_map->head && reasm_map->head - reasm_map->tail <= FD_REASM_MAP_COL_CNT );
     393             : 
     394           0 :   ulong col_idx = fec_msg->slot & (FD_REASM_MAP_COL_CNT - 1);
     395           0 :   struct fd_rpc_reasm_map_column * col = &reasm_map->cols[col_idx];
     396             : 
     397           0 :   if( col->ele_cnt ) {
     398           0 :     FD_TEST( fec_msg->fec_set_idx > col->ele[col->ele_cnt-1].fec_set_idx );
     399           0 :   }
     400             : 
     401           0 :   FD_TEST( col->ele_cnt < FD_REASM_MAP_COL_HEIGHT );
     402             : 
     403           0 :   col->ele[col->ele_cnt++] = *fec_msg;
     404             : 
     405           0 :   if( fec_msg->slot_complete ) {
     406             :     /* We've received all the shreds for this slot. Process it. */
     407           0 :     fd_rpc_history_process_column( hist, col, store, fec_msg );
     408           0 :     fd_rpc_history_discard_column( reasm_map, fec_msg->slot );
     409           0 :   }
     410           0 : }
     411             : 
     412             : ulong
     413           0 : fd_rpc_history_first_slot(fd_rpc_history_t * hist) {
     414           0 :   return hist->first_slot;
     415           0 : }
     416             : 
     417             : ulong
     418           0 : fd_rpc_history_latest_slot(fd_rpc_history_t * hist) {
     419           0 :   return hist->latest_slot;
     420           0 : }
     421             : 
     422             : fd_replay_slot_completed_t *
     423           0 : fd_rpc_history_get_block_info(fd_rpc_history_t * hist, ulong slot) {
     424           0 :   fd_rpc_block_t * blk = fd_rpc_block_map_query( hist->block_map, &slot, NULL );
     425           0 :   if( !blk ) {
     426           0 :     return NULL;
     427           0 :   }
     428           0 :   return &blk->info;
     429           0 : }
     430             : 
     431             : fd_replay_slot_completed_t *
     432           0 : fd_rpc_history_get_block_info_by_hash(fd_rpc_history_t * hist, fd_hash_t * h) {
     433           0 :   for( fd_rpc_block_map_iter_t i = fd_rpc_block_map_iter_init( hist->block_map );
     434           0 :        !fd_rpc_block_map_iter_done( hist->block_map, i );
     435           0 :        i = fd_rpc_block_map_iter_next( hist->block_map, i ) ) {
     436           0 :     fd_rpc_block_t * ele = fd_rpc_block_map_iter_ele( hist->block_map, i );
     437           0 :     if( fd_hash_eq( &ele->info.block_hash, h ) ) return &ele->info;
     438           0 :   }
     439           0 :   return NULL;
     440           0 : }
     441             : 
     442             : uchar *
     443           0 : fd_rpc_history_get_block(fd_rpc_history_t * hist, ulong slot, ulong * blk_sz) {
     444           0 :   fd_rpc_block_t * blk = fd_rpc_block_map_query( hist->block_map, &slot, NULL );
     445           0 :   if( !blk ) {
     446           0 :     *blk_sz = ULONG_MAX;
     447           0 :     return NULL;
     448           0 :   }
     449           0 :   uchar * blk_data = fd_spad_alloc( hist->spad, 1, blk->file_size );
     450           0 :   if( pread( hist->file_fd, blk_data, blk->file_size, (long)blk->file_offset ) != (ssize_t)blk->file_size ) {
     451           0 :     FD_LOG_ERR(( "unable to read rpc history file" ));
     452           0 :     *blk_sz = ULONG_MAX;
     453           0 :     return NULL;
     454           0 :   }
     455           0 :   *blk_sz = blk->file_size;
     456           0 :   return blk_data;
     457           0 : }
     458             : 
     459             : uchar *
     460           0 : fd_rpc_history_get_txn(fd_rpc_history_t * hist, fd_rpc_txn_key_t * sig, ulong * txn_sz, ulong * slot) {
     461           0 :   fd_rpc_txn_t * txn = fd_rpc_txn_map_query( hist->txn_map, sig, NULL );
     462           0 :   if( !txn ) {
     463           0 :     *txn_sz = ULONG_MAX;
     464           0 :     return NULL;
     465           0 :   }
     466           0 :   uchar * txn_data = fd_spad_alloc( hist->spad, 1, txn->file_size );
     467           0 :   if( pread( hist->file_fd, txn_data, txn->file_size, (long)txn->file_offset ) != (ssize_t)txn->file_size ) {
     468           0 :     FD_LOG_ERR(( "unable to read rpc history file" ));
     469           0 :     *txn_sz = ULONG_MAX;
     470           0 :     return NULL;
     471           0 :   }
     472           0 :   *txn_sz = txn->file_size;
     473           0 :   *slot = txn->slot;
     474           0 :   return txn_data;
     475           0 : }
     476             : 
     477             : const void *
     478           0 : fd_rpc_history_first_txn_for_acct(fd_rpc_history_t * hist, fd_pubkey_t * acct, fd_rpc_txn_key_t * sig, ulong * slot) {
     479           0 :   fd_rpc_acct_map_elem_t const * ele = fd_rpc_acct_map_ele_query_const( hist->acct_map, acct, NULL, hist->acct_pool );
     480           0 :   if( ele == NULL ) return NULL;
     481           0 :   *sig = ele->sig;
     482           0 :   *slot = ele->slot;
     483           0 :   return ele;
     484           0 : }
     485             : 
     486             : const void *
     487           0 : fd_rpc_history_next_txn_for_acct(fd_rpc_history_t * hist, fd_rpc_txn_key_t * sig, ulong * slot, const void * iter) {
     488           0 :   fd_rpc_acct_map_elem_t const * ele = (fd_rpc_acct_map_elem_t const *)iter;
     489           0 :   ele = fd_rpc_acct_map_ele_next_const( ele, NULL, hist->acct_pool );
     490           0 :   if( ele == NULL ) return NULL;
     491           0 :   *sig = ele->sig;
     492           0 :   *slot = ele->slot;
     493           0 :   return ele;
     494           0 : }

Generated by: LCOV version 1.14