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