LCOV - code coverage report
Current view: top level - discof/restore/utils - fd_slot_delta_parser.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 326 342 95.3 %
Date: 2026-09-17 04:28:31 Functions: 15 15 100.0 %

          Line data    Source code
       1             : #include "fd_slot_delta_parser.h"
       2             : 
       3             : #define SLOT_DELTA_PARSER_DEBUG 0
       4             : 
       5         459 : #define STATE_SLOT_DELTAS_LEN                                    ( 0)
       6       14112 : #define STATE_SLOT_DELTA_SLOT                                    ( 1)
       7       14097 : #define STATE_SLOT_DELTA_IS_ROOT                                 ( 2)
       8       11268 : #define STATE_SLOT_DELTA_STATUS_LEN                              ( 3)
       9         600 : #define STATE_STATUS_BLOCKHASH                                   ( 4)
      10         747 : #define STATE_STATUS_TXN_IDX                                     ( 5)
      11         585 : #define STATE_CACHE_STATUS_LEN                                   ( 6)
      12      862824 : #define STATE_CACHE_STATUS_KEY_SLICE                             ( 7)
      13      862824 : #define STATE_CACHE_STATUS_RESULT                                ( 8)
      14         348 : #define STATE_CACHE_STATUS_RESULT_ERR                            ( 9)
      15         204 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX                  (10)
      16         204 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR                  (11)
      17          72 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM           (12)
      18          60 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN (13)
      19          57 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR (14)
      20          72 : #define STATE_CACHE_STATUS_RESULT_ERR_IDX                        (15)
      21         249 : #define STATE_DONE                                               (16)
      22             : 
      23          42 : #define FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES (512UL)
      24             : 
      25             : struct fd_slot_delta_parser_private {
      26             :   int     state;                       /* parser state machine */
      27             :   int     entry_avail;                 /* whether a parsed entry is available */
      28             :   int     group_avail;                 /* whether a parsed group is available */
      29             :   int     slot_avail;                  /* whether a parsed slot is available */
      30             : 
      31             :   uchar * dst;                         /* where to store the next parsed value */
      32             :   ulong   dst_cur;                     /* offset into dst */
      33             :   ulong   dst_sz;                      /* size of dst */
      34             : 
      35             :   ulong   len;                         /* number of slot delta entries */
      36             :   int     is_root;                     /* whether the current slot delta entry is rooted */
      37             :   ulong   txnhash_offset;              /* offset into the txncache for the current slot delta entry */
      38             :   ulong   slot_delta_status_len;       /* number of blockhashes in the slot delta entry */
      39             :   ulong   cache_status_len;            /* number of txns associated with the blockhash */
      40             :   ulong   borsh_io_error_len;          /* used to parse a variable len borsh_io_error string */
      41             :   uint    error_discriminant;          /* stores the error discriminant of a txn result */
      42             :   uchar   error;                       /* stores the error code of a txn result */
      43             : 
      44             :   fd_slot_entry_t * slot_pool;         /* pool backing a slot hashset */
      45             :   slot_set_t *      slot_set;          /* slot hash set to detect duplicate slots */
      46             :   ulong             slot_pool_ele_cnt; /* count of slots in pool */
      47             :   fd_sstxncache_entry_t entry[1];      /* parsed slot delta entry */
      48             : };
      49             : 
      50             : static inline ulong
      51      440739 : state_size( fd_slot_delta_parser_t * parser ) {
      52      440739 :   switch( parser->state ) {
      53          96 :     case STATE_SLOT_DELTAS_LEN:                                    return sizeof(ulong);
      54        2823 :     case STATE_SLOT_DELTA_SLOT:                                    return sizeof(ulong);
      55        2820 :     case STATE_SLOT_DELTA_IS_ROOT:                                 return sizeof(uchar);
      56        2817 :     case STATE_SLOT_DELTA_STATUS_LEN:                              return sizeof(ulong);
      57         150 :     case STATE_STATUS_BLOCKHASH:                                   return 32UL;
      58         150 :     case STATE_STATUS_TXN_IDX:                                     return sizeof(ulong);
      59         147 :     case STATE_CACHE_STATUS_LEN:                                   return sizeof(ulong);
      60      215706 :     case STATE_CACHE_STATUS_KEY_SLICE:                             return 20UL;
      61      215706 :     case STATE_CACHE_STATUS_RESULT:                                return sizeof(uint);
      62          87 :     case STATE_CACHE_STATUS_RESULT_ERR:                            return sizeof(uint);
      63          51 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX:                  return sizeof(uchar);
      64          51 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR:                  return sizeof(uint);
      65          18 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM:           return sizeof(uint);
      66          15 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN: return sizeof(ulong);
      67          15 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR: return parser->borsh_io_error_len;
      68          18 :     case STATE_CACHE_STATUS_RESULT_ERR_IDX:                        return sizeof(uchar);
      69          69 :     case STATE_DONE:                                               return 0UL;
      70           0 :     default: FD_LOG_ERR(( "unknown state %d", parser->state ));
      71      440739 :   }
      72      440739 : }
      73             : 
      74             : static inline uchar *
      75      440739 : state_dst( fd_slot_delta_parser_t * parser ) {
      76      440739 :   switch( parser->state ) {
      77          96 :     case STATE_SLOT_DELTAS_LEN:                                    return (uchar*)&parser->len;
      78        2823 :     case STATE_SLOT_DELTA_SLOT:                                    return (uchar*)&parser->entry->slot;
      79        2820 :     case STATE_SLOT_DELTA_IS_ROOT:                                 return (uchar*)&parser->is_root;
      80        2817 :     case STATE_SLOT_DELTA_STATUS_LEN:                              return (uchar*)&parser->slot_delta_status_len;
      81         150 :     case STATE_STATUS_BLOCKHASH:                                   return parser->entry->blockhash;
      82         150 :     case STATE_STATUS_TXN_IDX:                                     return (uchar*)&parser->txnhash_offset;
      83         147 :     case STATE_CACHE_STATUS_LEN:                                   return (uchar*)&parser->cache_status_len;
      84      215706 :     case STATE_CACHE_STATUS_KEY_SLICE:                             return parser->entry->txnhash;
      85      215706 :     case STATE_CACHE_STATUS_RESULT:                                return (uchar*)&parser->error_discriminant;
      86          87 :     case STATE_CACHE_STATUS_RESULT_ERR:                            return (uchar*)&parser->error_discriminant;
      87          51 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX:                  return NULL;
      88          51 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR:                  return (uchar*)&parser->error_discriminant;
      89          18 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM:           return (uchar*)&parser->error_discriminant;
      90          15 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN: return (uchar*)&parser->borsh_io_error_len;
      91          15 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR: return NULL;
      92          18 :     case STATE_CACHE_STATUS_RESULT_ERR_IDX:                        return (uchar*)&parser->error;
      93          69 :     case STATE_DONE:                                               return NULL;
      94           0 :     default: FD_LOG_ERR(( "unknown state %d", parser->state ));
      95      440739 :   }
      96      440739 : }
      97             : 
      98             : #if SLOT_DELTA_PARSER_DEBUG
      99             : static inline void
     100             : state_log( fd_slot_delta_parser_t * parser ) {
     101             :   switch( parser->state ) {
     102             :     case STATE_SLOT_DELTAS_LEN:        FD_LOG_NOTICE(( "STATE_SLOT_DELTAS_LEN:        %lu", parser->len ));                                         break;
     103             :     case STATE_SLOT_DELTA_SLOT:        FD_LOG_NOTICE(( "STATE_SLOT_DELTA_SLOT:        %lu", parser->entry->slot ));                                 break;
     104             :     case STATE_SLOT_DELTA_IS_ROOT:     FD_LOG_NOTICE(( "STATE_SLOT_DELTA_IS_ROOT:     %d",  parser->is_root ));                                     break;
     105             :     case STATE_SLOT_DELTA_STATUS_LEN:  FD_LOG_NOTICE(( "STATE_SLOT_DELTA_STATUS_LEN:  %lu", parser->slot_delta_status_len ));                       break;
     106             :     case STATE_STATUS_BLOCKHASH: {
     107             :       FD_BASE58_ENCODE_32_BYTES( parser->entry->blockhash, blockhash_b58 );
     108             :       /*                             */FD_LOG_NOTICE(( "STATE_STATUS_BLOCKHASH:       %s",  blockhash_b58 ));
     109             :       break;
     110             :     }
     111             :     case STATE_CACHE_STATUS_LEN:       FD_LOG_NOTICE(( "STATE_CACHE_STATUS_LEN:       %lu", parser->cache_status_len ));                            break;
     112             :     default: break;
     113             :   }
     114             : }
     115             : #endif
     116             : 
     117             : static inline int
     118      440655 : state_validate( fd_slot_delta_parser_t * parser ) {
     119      440655 :   switch( parser->state ) {
     120          87 :     case STATE_SLOT_DELTAS_LEN:
     121          87 :       if( FD_UNLIKELY( parser->len>FD_SLOT_DELTA_MAX_ENTRIES ) ) {
     122             :         /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/snapshot_bank_utils.rs#L535 */
     123           3 :         FD_LOG_WARNING(( "slot delta validation failed: %s (%d)", fd_slot_delta_parser_advance_str( FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES ), FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES ));
     124           3 :         return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES;
     125           3 :       }
     126          84 :       break;
     127        2823 :     case STATE_SLOT_DELTA_SLOT: {
     128        2823 :       ulong slot_idx = slot_set_idx_query_const( parser->slot_set, &parser->entry->slot, ULONG_MAX, parser->slot_pool );
     129             :       /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/snapshot_bank_utils.rs#L558 */
     130        2823 :       if( FD_UNLIKELY( slot_idx!=ULONG_MAX ) ) {
     131           3 :         FD_LOG_WARNING(( "slot delta validation failed: %s (%d)", fd_slot_delta_parser_advance_str( FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_HASH_MULTIPLE_ENTRIES ), FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_HASH_MULTIPLE_ENTRIES ));
     132           3 :         return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_HASH_MULTIPLE_ENTRIES;
     133           3 :       }
     134             : 
     135        2820 :       if( FD_UNLIKELY( parser->slot_pool_ele_cnt>=FD_SLOT_DELTA_MAX_ENTRIES ) ) {
     136             :         /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/snapshot_bank_utils.rs#L535 */
     137           0 :         FD_LOG_WARNING(( "slot delta validation failed: %s (%d)", fd_slot_delta_parser_advance_str( FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES ), FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES ));
     138           0 :         return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES;
     139           0 :       }
     140             : 
     141        2820 :       fd_slot_entry_t * slot_entry = &parser->slot_pool[ parser->slot_pool_ele_cnt++ ];
     142        2820 :       slot_entry->slot             = parser->entry->slot;
     143        2820 :       slot_set_ele_insert( parser->slot_set, slot_entry, parser->slot_pool );
     144        2820 :       break;
     145        2820 :     }
     146        2820 :     case STATE_SLOT_DELTA_IS_ROOT:
     147        2820 :       if( FD_UNLIKELY( !parser->is_root) ) {
     148             :         /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/snapshot_bank_utils.rs#L545 */
     149           3 :         FD_LOG_WARNING(( "slot delta validation failed: %s (%d)", fd_slot_delta_parser_advance_str( FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_IS_NOT_ROOT ), FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_IS_NOT_ROOT ));
     150           3 :         return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_IS_NOT_ROOT;
     151           3 :       }
     152        2817 :       break;
     153        2817 :     case STATE_STATUS_TXN_IDX:
     154         150 :       if( FD_UNLIKELY( parser->txnhash_offset>FD_SLOT_DELTA_MAX_TXNHASH_OFFSET ) ) {
     155           3 :         FD_LOG_WARNING(( "slot delta validation failed: %s (%d)",
     156           3 :                          fd_slot_delta_parser_advance_str( FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_INVALID_TXNHASH_OFFSET ),
     157           3 :                          FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_INVALID_TXNHASH_OFFSET ));
     158           3 :         return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_INVALID_TXNHASH_OFFSET;
     159           3 :       }
     160         147 :       break;
     161      434775 :     default: break;
     162      440655 :   }
     163             : 
     164      440643 :   return 0;
     165      440655 : }
     166             : 
     167             : static inline void
     168      218421 : loop( fd_slot_delta_parser_t * parser ) {
     169      218421 :   if( FD_LIKELY( parser->cache_status_len ) ) {
     170      215577 :     parser->state = STATE_CACHE_STATUS_KEY_SLICE;
     171      215577 :   } else if( FD_LIKELY( parser->slot_delta_status_len ) ) {
     172          36 :     parser->state = STATE_STATUS_BLOCKHASH;
     173        2808 :   } else if( FD_LIKELY( parser->len ) ) {
     174        2745 :     parser->state = STATE_SLOT_DELTA_SLOT;
     175        2745 :   } else {
     176          63 :     parser->state = STATE_DONE;
     177          63 :   }
     178      218421 : }
     179             : 
     180             : static inline void
     181      215703 : result_loop( fd_slot_delta_parser_t * parser ) {
     182      215703 :   parser->entry_avail = 1;
     183      215703 :   loop( parser );
     184      215703 : }
     185             : 
     186             : static inline void
     187      440643 : state_process( fd_slot_delta_parser_t * parser ) {
     188      440643 :   FD_TEST( parser->state!=STATE_DONE );
     189             : 
     190      440643 :   switch( parser->state ) {
     191          84 :     case STATE_SLOT_DELTAS_LEN:
     192          84 :       if( FD_UNLIKELY( !parser->len ) ) parser->state = STATE_DONE;
     193          78 :       else                              parser->state = STATE_SLOT_DELTA_SLOT;
     194          84 :       break;
     195        2820 :     case STATE_SLOT_DELTA_SLOT:
     196        2820 :       parser->state = STATE_SLOT_DELTA_IS_ROOT;
     197        2820 :       parser->len--;
     198        2820 :       break;
     199        2817 :     case STATE_SLOT_DELTA_IS_ROOT:
     200        2817 :       parser->state = STATE_SLOT_DELTA_STATUS_LEN;
     201        2817 :       break;
     202        2817 :     case STATE_SLOT_DELTA_STATUS_LEN:
     203        2817 :       parser->slot_avail = 1;
     204        2817 :       if( FD_UNLIKELY( !parser->slot_delta_status_len ) ) loop( parser );
     205         114 :       else                                                parser->state = STATE_STATUS_BLOCKHASH;
     206        2817 :       break;
     207         150 :     case STATE_STATUS_BLOCKHASH:
     208         150 :       parser->state = STATE_STATUS_TXN_IDX;
     209         150 :       parser->slot_delta_status_len--;
     210         150 :       break;
     211         147 :     case STATE_STATUS_TXN_IDX:
     212         147 :       parser->state       = STATE_CACHE_STATUS_LEN;
     213         147 :       parser->group_avail = 1;
     214         147 :       break;
     215         144 :     case STATE_CACHE_STATUS_LEN:
     216         144 :       if( FD_UNLIKELY( !parser->cache_status_len ) ) loop( parser );
     217         129 :       else                                           parser->state = STATE_CACHE_STATUS_KEY_SLICE;
     218         144 :       break;
     219      215706 :     case STATE_CACHE_STATUS_KEY_SLICE:
     220      215706 :       parser->state = STATE_CACHE_STATUS_RESULT;
     221      215706 :       parser->cache_status_len--;
     222      215706 :       break;
     223      215706 :     case STATE_CACHE_STATUS_RESULT:
     224      215706 :       if( FD_LIKELY( !parser->error_discriminant ) ) {
     225      215619 :         parser->entry->result = 0;
     226      215619 :         result_loop( parser );
     227      215619 :       }
     228          87 :       else {
     229          87 :         parser->state = STATE_CACHE_STATUS_RESULT_ERR;
     230          87 :       }
     231      215706 :       break;
     232          87 :     case STATE_CACHE_STATUS_RESULT_ERR:
     233          87 :       if( FD_UNLIKELY( parser->error_discriminant==8U ) ) {
     234          51 :         parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX;
     235          51 :       } else if( FD_UNLIKELY( parser->error_discriminant==30U || parser->error_discriminant==31U || parser->error_discriminant==35U ) ) {
     236          18 :         parser->state = STATE_CACHE_STATUS_RESULT_ERR_IDX;
     237          18 :       } else {
     238          18 :         parser->entry->result = (uchar)parser->error_discriminant;
     239          18 :         result_loop( parser );
     240          18 :       }
     241          87 :     break;
     242          51 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX:
     243          51 :       parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR;
     244          51 :       break;
     245          51 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR:
     246          51 :       if( FD_UNLIKELY( parser->error_discriminant==25U ) ) {
     247          18 :         parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM;
     248          33 :       } else if( FD_UNLIKELY( parser->error_discriminant==44U ) ) {
     249          15 :         parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN;
     250          18 :       } else {
     251          18 :         parser->entry->result = (uchar)parser->error_discriminant;
     252          18 :         result_loop( parser );
     253          18 :       }
     254          51 :       break;
     255          18 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM:
     256          18 :       parser->entry->result = (uchar)parser->error_discriminant;
     257          18 :       result_loop( parser );
     258          18 :       break;
     259          15 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN:
     260          15 :       parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR;
     261          15 :       break;
     262          12 :     case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR:
     263          12 :       parser->entry->result = (uchar)parser->error_discriminant;
     264          12 :       result_loop( parser );
     265          12 :       break;
     266          18 :     case STATE_CACHE_STATUS_RESULT_ERR_IDX:
     267          18 :       parser->entry->result = (uchar)parser->error;
     268          18 :       result_loop( parser );
     269          18 :       break;
     270           0 :     default: FD_LOG_ERR(( "unknown state %d", parser->state ));
     271      440643 :   }
     272      440643 : }
     273             : 
     274             : FD_FN_CONST ulong
     275         360 : fd_slot_delta_parser_align( void ) {
     276         360 :   return fd_ulong_max( fd_ulong_max( alignof(fd_slot_delta_parser_t), slot_pool_align() ), slot_set_align() );
     277         360 : }
     278             : 
     279             : FD_FN_CONST ulong
     280          90 : fd_slot_delta_parser_footprint( void ) {
     281          90 :   ulong l = FD_LAYOUT_INIT;
     282          90 :   l = FD_LAYOUT_APPEND( l,  alignof(fd_slot_delta_parser_t), sizeof(fd_slot_delta_parser_t)                                  );
     283          90 :   l = FD_LAYOUT_APPEND( l,  slot_pool_align(),               slot_pool_footprint( FD_SLOT_DELTA_MAX_ENTRIES )                );
     284          90 :   l = FD_LAYOUT_APPEND( l,  slot_set_align(),                slot_set_footprint( FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES ) );
     285          90 :   return FD_LAYOUT_FINI( l, fd_slot_delta_parser_align() );
     286          90 : }
     287             : 
     288             : void *
     289          42 : fd_slot_delta_parser_new( void * shmem ) {
     290          42 :   if( FD_UNLIKELY( !shmem ) ) {
     291           0 :     FD_LOG_WARNING(( "NULL shmem" ));
     292           0 :     return NULL;
     293           0 :   }
     294             : 
     295          42 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_slot_delta_parser_align() ) ) ) {
     296           0 :     FD_LOG_WARNING(( "unaligned shmem" ));
     297           0 :     return NULL;
     298           0 :   }
     299             : 
     300          42 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
     301          42 :   fd_slot_delta_parser_t * parser = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_slot_delta_parser_t), sizeof(fd_slot_delta_parser_t)                                  );
     302          42 :   void * slot_pool_mem            = FD_SCRATCH_ALLOC_APPEND( l, slot_pool_align(),               slot_pool_footprint( FD_SLOT_DELTA_MAX_ENTRIES )                );
     303          42 :   void * slot_set_mem             = FD_SCRATCH_ALLOC_APPEND( l, slot_set_align(),                slot_set_footprint( FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES ) );
     304          42 :   FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_slot_delta_parser_align() ) == (ulong)shmem + fd_slot_delta_parser_footprint() );
     305             : 
     306          42 :   parser->slot_pool = slot_pool_join( slot_pool_new( slot_pool_mem, FD_SLOT_DELTA_MAX_ENTRIES ) );
     307          42 :   FD_TEST( parser->slot_pool );
     308             : 
     309          42 :   parser->slot_set = slot_set_join( slot_set_new( slot_set_mem, FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES, 1UL ) );
     310          42 :   FD_TEST( parser->slot_set );
     311             : 
     312       12642 :   for( ulong i=0UL; i<slot_pool_max( parser->slot_pool ); i++ ) {
     313       12600 :     fd_slot_entry_t * slot_entry = &parser->slot_pool[ i ];
     314       12600 :     slot_entry->slot = ULONG_MAX;
     315       12600 :   }
     316             : 
     317          42 :   parser->entry_avail       = 0;
     318          42 :   parser->group_avail       = 0;
     319          42 :   parser->slot_avail        = 0;
     320          42 :   parser->slot_pool_ele_cnt = 0UL;
     321          42 :   parser->state             = STATE_DONE;
     322             : 
     323          42 :   return parser;
     324          42 : }
     325             : 
     326             : fd_slot_delta_parser_t *
     327          42 : fd_slot_delta_parser_join( void * shmem ) {
     328          42 :   return shmem;
     329          42 : }
     330             : 
     331             : void *
     332          24 : fd_slot_delta_parser_leave( fd_slot_delta_parser_t * parser ) {
     333          24 :   return (void *)parser;
     334          24 : }
     335             : 
     336             : void *
     337          24 : fd_slot_delta_parser_delete( void * shmem ) {
     338          24 :   return shmem;
     339          24 : }
     340             : 
     341             : void
     342          96 : fd_slot_delta_parser_init( fd_slot_delta_parser_t * parser ) {
     343          96 :   parser->state     = STATE_SLOT_DELTAS_LEN;
     344          96 :   parser->len       = 0UL;
     345          96 :   parser->is_root   = 0;
     346             : 
     347          96 :   parser->slot_delta_status_len = 0UL;
     348          96 :   parser->cache_status_len      = 0UL;
     349          96 :   parser->borsh_io_error_len    = 0UL;
     350          96 :   parser->error_discriminant    = 0U;
     351             : 
     352         165 :   for( ulong i=0UL; i<parser->slot_pool_ele_cnt; i++ ) {
     353          69 :     fd_slot_entry_t * slot_entry = &parser->slot_pool[ i ];
     354          69 :     slot_set_ele_remove_fast( parser->slot_set, slot_entry, parser->slot_pool );
     355          69 :     slot_entry->slot = ULONG_MAX;
     356          69 :   }
     357             : 
     358          96 :   parser->slot_pool_ele_cnt = 0UL;
     359             : 
     360          96 :   parser->dst       = state_dst( parser );
     361          96 :   parser->dst_sz    = state_size( parser );
     362          96 :   parser->dst_cur   = 0UL;
     363             : 
     364          96 :   parser->entry_avail = 0;
     365          96 :   parser->group_avail = 0;
     366          96 :   parser->slot_avail  = 0;
     367          96 : }
     368             : 
     369             : int
     370             : fd_slot_delta_parser_consume( fd_slot_delta_parser_t *                parser,
     371             :                               uchar const *                           buf,
     372             :                               ulong                                   bufsz,
     373      218730 :                               fd_slot_delta_parser_advance_result_t * result ) {
     374      218730 :   uchar const * data    = buf;
     375      218730 :   ulong         data_sz = bufsz;
     376      440706 :   while( data_sz || parser->dst_cur==parser->dst_sz ) {
     377      440700 :     if( FD_UNLIKELY( parser->state==STATE_DONE ) ) break;
     378             : 
     379      440655 :     ulong consume = fd_ulong_min( data_sz, parser->dst_sz-parser->dst_cur );
     380             : 
     381      440655 :     if( FD_LIKELY( parser->dst && consume ) ) {
     382      440592 :       memcpy( parser->dst+parser->dst_cur, data, consume );
     383      440592 :     }
     384             : 
     385      440655 :     parser->dst_cur += consume;
     386      440655 :     data            += consume;
     387      440655 :     data_sz         -= consume;
     388             : 
     389             : #if SLOT_DELTA_PARSER_DEBUG
     390             :     state_log( parser );
     391             : #endif
     392             : 
     393      440655 :     if( FD_LIKELY( parser->dst_cur==parser->dst_sz ) ) {
     394      440655 :       int err = state_validate( parser );
     395      440655 :       if( FD_UNLIKELY( err ) ) {
     396          12 :         result->bytes_consumed = (ulong)(data - buf);
     397          12 :         return err;
     398          12 :       }
     399             : 
     400      440643 :       state_process( parser );
     401             : 
     402      440643 :       parser->dst     = state_dst( parser );
     403      440643 :       parser->dst_sz  = state_size( parser );
     404      440643 :       parser->dst_cur = 0UL;
     405             : 
     406      440643 :       if( FD_LIKELY( parser->slot_avail ) ) {
     407        2817 :         FD_TEST( parser->entry_avail==0 );
     408        2817 :         FD_TEST( parser->group_avail==0 );
     409        2817 :         parser->slot_avail      = 0;
     410        2817 :         result->slot            = parser->entry->slot;
     411        2817 :         result->bytes_consumed  = (ulong)(data - buf);
     412        2817 :         return FD_SLOT_DELTA_PARSER_ADVANCE_SLOT;
     413      437826 :       } else if( FD_LIKELY( parser->group_avail ) ) {
     414         147 :         FD_TEST( parser->entry_avail==0 );
     415         147 :         FD_TEST( parser->slot_avail==0 );
     416         147 :         parser->group_avail          = 0;
     417         147 :         result->entry                = NULL;
     418         147 :         result->group.blockhash      = parser->entry->blockhash;
     419         147 :         result->group.txnhash_offset = parser->txnhash_offset;
     420         147 :         result->group.slot           = parser->entry->slot;
     421         147 :         result->bytes_consumed       = (ulong)(data - buf);
     422         147 :         return FD_SLOT_DELTA_PARSER_ADVANCE_GROUP;
     423      437679 :       } else if( FD_LIKELY( parser->entry_avail ) ) {
     424      215703 :         FD_TEST( parser->group_avail==0 );
     425      215703 :         FD_TEST( parser->slot_avail==0 );
     426      215703 :         parser->entry_avail    = 0;
     427      215703 :         result->entry          = parser->entry;
     428      215703 :         result->bytes_consumed = (ulong)(data - buf);
     429      215703 :         return FD_SLOT_DELTA_PARSER_ADVANCE_ENTRY;
     430      215703 :       }
     431      440643 :     }
     432      440655 :   }
     433             : 
     434          51 :   if( FD_UNLIKELY( data_sz ) ) {
     435           0 :     FD_LOG_WARNING(( "excess data in buffer" ));
     436           0 :     result->bytes_consumed = (ulong)(data - buf);
     437           0 :     return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_EXCESS_DATA_IN_BUFFER;
     438           0 :   }
     439             : 
     440          51 :   result->bytes_consumed = (ulong)(data - buf);
     441          51 :   if( FD_LIKELY( parser->state==STATE_DONE ) ) return FD_SLOT_DELTA_PARSER_ADVANCE_DONE;
     442             : 
     443           6 :   if( FD_UNLIKELY( !bufsz ) ) {
     444           3 :     FD_LOG_WARNING(( "unexpected end of data while parsing slot delta, state=%d, dst_cur=%lu, dst_sz=%lu",
     445           3 :                      parser->state, parser->dst_cur, parser->dst_sz ));
     446           3 :     return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_UNEXPECTED_EOF;
     447           3 :   }
     448             : 
     449           3 :   return FD_SLOT_DELTA_PARSER_ADVANCE_AGAIN;
     450           6 : }
     451             : 
     452             : fd_slot_delta_slot_set_t
     453          30 : fd_slot_delta_parser_slot_set( fd_slot_delta_parser_t * parser ) {
     454          30 :   return (fd_slot_delta_slot_set_t){
     455          30 :     .map  = parser->slot_set,
     456          30 :     .pool = parser->slot_pool,
     457          30 :     .ele_cnt   = parser->slot_pool_ele_cnt
     458          30 :   };
     459          30 : }

Generated by: LCOV version 1.14