Line data Source code
1 : #include "fd_slot_delta_parser.h" 2 : 3 : #define SLOT_DELTA_PARSER_DEBUG 0 4 : 5 0 : #define STATE_SLOT_DELTAS_LEN ( 0) 6 0 : #define STATE_SLOT_DELTA_SLOT ( 1) 7 0 : #define STATE_SLOT_DELTA_IS_ROOT ( 2) 8 0 : #define STATE_SLOT_DELTA_STATUS_LEN ( 3) 9 0 : #define STATE_STATUS_BLOCKHASH ( 4) 10 0 : #define STATE_STATUS_TXN_IDX ( 5) 11 0 : #define STATE_CACHE_STATUS_LEN ( 6) 12 0 : #define STATE_CACHE_STATUS_KEY_SLICE ( 7) 13 0 : #define STATE_CACHE_STATUS_RESULT ( 8) 14 0 : #define STATE_CACHE_STATUS_RESULT_ERR ( 9) 15 0 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX (10) 16 0 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR (11) 17 0 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM (12) 18 0 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN (13) 19 0 : #define STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR (14) 20 0 : #define STATE_CACHE_STATUS_RESULT_ERR_IDX (15) 21 0 : #define STATE_DONE (16) 22 : 23 0 : #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 0 : state_size( fd_slot_delta_parser_t * parser ) { 51 0 : switch( parser->state ) { 52 0 : case STATE_SLOT_DELTAS_LEN: return sizeof(ulong); 53 0 : case STATE_SLOT_DELTA_SLOT: return sizeof(ulong); 54 0 : case STATE_SLOT_DELTA_IS_ROOT: return sizeof(uchar); 55 0 : case STATE_SLOT_DELTA_STATUS_LEN: return sizeof(ulong); 56 0 : case STATE_STATUS_BLOCKHASH: return 32UL; 57 0 : case STATE_STATUS_TXN_IDX: return sizeof(ulong); 58 0 : case STATE_CACHE_STATUS_LEN: return sizeof(ulong); 59 0 : case STATE_CACHE_STATUS_KEY_SLICE: return 20UL; 60 0 : case STATE_CACHE_STATUS_RESULT: return sizeof(uint); 61 0 : case STATE_CACHE_STATUS_RESULT_ERR: return sizeof(uint); 62 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX: return sizeof(uchar); 63 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR: return sizeof(uint); 64 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM: return sizeof(uint); 65 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN: return sizeof(ulong); 66 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR: return parser->borsh_io_error_len; 67 0 : case STATE_CACHE_STATUS_RESULT_ERR_IDX: return sizeof(uchar); 68 0 : case STATE_DONE: return 0UL; 69 0 : default: FD_LOG_ERR(( "unknown state %d", parser->state )); 70 0 : } 71 0 : } 72 : 73 : static inline uchar * 74 0 : state_dst( fd_slot_delta_parser_t * parser ) { 75 0 : switch( parser->state ) { 76 0 : case STATE_SLOT_DELTAS_LEN: return (uchar*)&parser->len; 77 0 : case STATE_SLOT_DELTA_SLOT: return (uchar*)&parser->entry->slot; 78 0 : case STATE_SLOT_DELTA_IS_ROOT: return (uchar*)&parser->is_root; 79 0 : case STATE_SLOT_DELTA_STATUS_LEN: return (uchar*)&parser->slot_delta_status_len; 80 0 : case STATE_STATUS_BLOCKHASH: return parser->entry->blockhash; 81 0 : case STATE_STATUS_TXN_IDX: return (uchar*)&parser->txnhash_offset; 82 0 : case STATE_CACHE_STATUS_LEN: return (uchar*)&parser->cache_status_len; 83 0 : case STATE_CACHE_STATUS_KEY_SLICE: return parser->entry->txnhash; 84 0 : case STATE_CACHE_STATUS_RESULT: return (uchar*)&parser->error_discriminant; 85 0 : case STATE_CACHE_STATUS_RESULT_ERR: return (uchar*)&parser->error_discriminant; 86 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX: return NULL; 87 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR: return (uchar*)&parser->error_discriminant; 88 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM: return (uchar*)&parser->error_discriminant; 89 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN: return (uchar*)&parser->borsh_io_error_len; 90 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR: return NULL; 91 0 : case STATE_CACHE_STATUS_RESULT_ERR_IDX: return (uchar*)&parser->error; 92 0 : case STATE_DONE: return NULL; 93 0 : default: FD_LOG_ERR(( "unknown state %d", parser->state )); 94 0 : } 95 0 : } 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 0 : state_validate( fd_slot_delta_parser_t * parser ) { 118 0 : switch( parser->state ) { 119 0 : case STATE_SLOT_DELTAS_LEN: 120 0 : 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 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 )); 123 0 : return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES; 124 0 : } 125 0 : break; 126 0 : case STATE_SLOT_DELTA_SLOT: { 127 0 : 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 0 : if( FD_UNLIKELY( slot_idx!=ULONG_MAX ) ) { 130 0 : 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 0 : return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_HASH_MULTIPLE_ENTRIES; 132 0 : } 133 : 134 0 : 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 0 : fd_slot_entry_t * slot_entry = &parser->slot_pool[ parser->slot_pool_ele_cnt++ ]; 141 0 : slot_entry->slot = parser->entry->slot; 142 0 : slot_set_ele_insert( parser->slot_set, slot_entry, parser->slot_pool ); 143 0 : break; 144 0 : } 145 0 : case STATE_SLOT_DELTA_IS_ROOT: 146 0 : 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 0 : 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 0 : return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_IS_NOT_ROOT; 150 0 : } 151 0 : break; 152 0 : default: break; 153 0 : } 154 : 155 0 : return 0; 156 0 : } 157 : 158 : static inline void 159 0 : loop( fd_slot_delta_parser_t * parser ) { 160 0 : if( FD_LIKELY( parser->cache_status_len ) ) { 161 0 : parser->state = STATE_CACHE_STATUS_KEY_SLICE; 162 0 : } else if( FD_LIKELY( parser->slot_delta_status_len ) ) { 163 0 : parser->state = STATE_STATUS_BLOCKHASH; 164 0 : } else if( FD_LIKELY( parser->len ) ) { 165 0 : parser->state = STATE_SLOT_DELTA_SLOT; 166 0 : } else { 167 0 : parser->state = STATE_DONE; 168 0 : } 169 0 : } 170 : 171 : static inline void 172 0 : result_loop( fd_slot_delta_parser_t * parser ) { 173 0 : parser->entry_avail = 1; 174 0 : loop( parser ); 175 0 : } 176 : 177 : static inline void 178 0 : state_process( fd_slot_delta_parser_t * parser ) { 179 0 : FD_TEST( parser->state!=STATE_DONE ); 180 : 181 0 : switch( parser->state ) { 182 0 : case STATE_SLOT_DELTAS_LEN: 183 0 : parser->state = STATE_SLOT_DELTA_SLOT; 184 0 : break; 185 0 : case STATE_SLOT_DELTA_SLOT: 186 0 : parser->state = STATE_SLOT_DELTA_IS_ROOT; 187 0 : parser->len--; 188 0 : break; 189 0 : case STATE_SLOT_DELTA_IS_ROOT: 190 0 : parser->state = STATE_SLOT_DELTA_STATUS_LEN; 191 0 : break; 192 0 : case STATE_SLOT_DELTA_STATUS_LEN: 193 0 : if( FD_UNLIKELY( !parser->slot_delta_status_len ) ) loop( parser ); 194 0 : else parser->state = STATE_STATUS_BLOCKHASH; 195 0 : break; 196 0 : case STATE_STATUS_BLOCKHASH: 197 0 : parser->state = STATE_STATUS_TXN_IDX; 198 0 : parser->slot_delta_status_len--; 199 0 : break; 200 0 : case STATE_STATUS_TXN_IDX: 201 0 : parser->state = STATE_CACHE_STATUS_LEN; 202 0 : parser->group_avail = 1; 203 0 : break; 204 0 : case STATE_CACHE_STATUS_LEN: 205 0 : if( FD_UNLIKELY( !parser->cache_status_len ) ) loop( parser ); 206 0 : else parser->state = STATE_CACHE_STATUS_KEY_SLICE; 207 0 : break; 208 0 : case STATE_CACHE_STATUS_KEY_SLICE: 209 0 : parser->state = STATE_CACHE_STATUS_RESULT; 210 0 : parser->cache_status_len--; 211 0 : break; 212 0 : case STATE_CACHE_STATUS_RESULT: 213 0 : if( FD_LIKELY( !parser->error_discriminant ) ) { 214 0 : parser->entry->result = 0; 215 0 : result_loop( parser ); 216 0 : } 217 0 : else { 218 0 : parser->state = STATE_CACHE_STATUS_RESULT_ERR; 219 0 : } 220 0 : break; 221 0 : case STATE_CACHE_STATUS_RESULT_ERR: 222 0 : if( FD_UNLIKELY( parser->error_discriminant==8U ) ) { 223 0 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX; 224 0 : } else if( FD_UNLIKELY( parser->error_discriminant==30U || parser->error_discriminant==31U || parser->error_discriminant==35U ) ) { 225 0 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_IDX; 226 0 : } else { 227 0 : parser->entry->result = (uchar)parser->error_discriminant; 228 0 : result_loop( parser ); 229 0 : } 230 0 : break; 231 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX: 232 0 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR; 233 0 : break; 234 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR: 235 0 : if( FD_UNLIKELY( parser->error_discriminant==25U ) ) { 236 0 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM; 237 0 : } else if( FD_UNLIKELY( parser->error_discriminant==44U ) ) { 238 0 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN; 239 0 : } else { 240 0 : parser->entry->result = (uchar)parser->error_discriminant; 241 0 : result_loop( parser ); 242 0 : } 243 0 : break; 244 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM: 245 0 : parser->entry->result = (uchar)parser->error_discriminant; 246 0 : result_loop( parser ); 247 0 : break; 248 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN: 249 0 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR; 250 0 : break; 251 0 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR: 252 0 : parser->entry->result = (uchar)parser->error_discriminant; 253 0 : result_loop( parser ); 254 0 : break; 255 0 : case STATE_CACHE_STATUS_RESULT_ERR_IDX: 256 0 : parser->entry->result = (uchar)parser->error; 257 0 : result_loop( parser ); 258 0 : break; 259 0 : default: FD_LOG_ERR(( "unknown state %d", parser->state )); 260 0 : } 261 0 : } 262 : 263 : FD_FN_CONST ulong 264 0 : fd_slot_delta_parser_align( void ) { 265 0 : return fd_ulong_max( fd_ulong_max( alignof(fd_slot_delta_parser_t), slot_pool_align() ), slot_set_align() ); 266 0 : } 267 : 268 : FD_FN_CONST ulong 269 0 : fd_slot_delta_parser_footprint( void ) { 270 0 : ulong l = FD_LAYOUT_INIT; 271 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_slot_delta_parser_t), sizeof(fd_slot_delta_parser_t) ); 272 0 : l = FD_LAYOUT_APPEND( l, slot_pool_align(), slot_pool_footprint( FD_SLOT_DELTA_MAX_ENTRIES ) ); 273 0 : l = FD_LAYOUT_APPEND( l, slot_set_align(), slot_set_footprint( FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES ) ); 274 0 : return FD_LAYOUT_FINI( l, fd_slot_delta_parser_align() ); 275 0 : } 276 : 277 : void * 278 0 : fd_slot_delta_parser_new( void * shmem ) { 279 0 : if( FD_UNLIKELY( !shmem ) ) { 280 0 : FD_LOG_WARNING(( "NULL shmem" )); 281 0 : return NULL; 282 0 : } 283 : 284 0 : 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 0 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 290 0 : fd_slot_delta_parser_t * parser = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_slot_delta_parser_t), sizeof(fd_slot_delta_parser_t) ); 291 0 : void * slot_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, slot_pool_align(), slot_pool_footprint( FD_SLOT_DELTA_MAX_ENTRIES ) ); 292 0 : void * slot_set_mem = FD_SCRATCH_ALLOC_APPEND( l, slot_set_align(), slot_set_footprint( FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES ) ); 293 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_slot_delta_parser_align() ) == (ulong)shmem + fd_slot_delta_parser_footprint() ); 294 : 295 0 : parser->slot_pool = slot_pool_join( slot_pool_new( slot_pool_mem, FD_SLOT_DELTA_MAX_ENTRIES ) ); 296 0 : FD_TEST( parser->slot_pool ); 297 : 298 0 : parser->slot_set = slot_set_join( slot_set_new( slot_set_mem, FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES, 1UL ) ); 299 0 : FD_TEST( parser->slot_set ); 300 : 301 0 : for( ulong i=0UL; i<slot_pool_max( parser->slot_pool ); i++ ) { 302 0 : fd_slot_entry_t * slot_entry = &parser->slot_pool[ i ]; 303 0 : slot_entry->slot = ULONG_MAX; 304 0 : } 305 : 306 0 : parser->entry_avail = 0; 307 0 : parser->group_avail = 0; 308 0 : parser->slot_pool_ele_cnt = 0UL; 309 0 : parser->state = STATE_DONE; 310 : 311 0 : return parser; 312 0 : } 313 : 314 : fd_slot_delta_parser_t * 315 0 : fd_slot_delta_parser_join( void * shmem ) { 316 0 : return shmem; 317 0 : } 318 : 319 : void * 320 0 : fd_slot_delta_parser_leave( fd_slot_delta_parser_t * parser ) { 321 0 : return (void *)parser; 322 0 : } 323 : 324 : void * 325 0 : fd_slot_delta_parser_delete( void * shmem ) { 326 0 : return shmem; 327 0 : } 328 : 329 : void 330 0 : fd_slot_delta_parser_init( fd_slot_delta_parser_t * parser ) { 331 0 : parser->state = STATE_SLOT_DELTAS_LEN; 332 0 : parser->len = 0UL; 333 0 : parser->is_root = 0; 334 : 335 0 : parser->slot_delta_status_len = 0UL; 336 0 : parser->cache_status_len = 0UL; 337 0 : parser->borsh_io_error_len = 0UL; 338 0 : parser->error_discriminant = 0U; 339 : 340 0 : for( ulong i=0UL; i<parser->slot_pool_ele_cnt; i++ ) { 341 0 : fd_slot_entry_t * slot_entry = &parser->slot_pool[ i ]; 342 0 : slot_set_ele_remove_fast( parser->slot_set, slot_entry, parser->slot_pool ); 343 0 : slot_entry->slot = ULONG_MAX; 344 0 : } 345 : 346 0 : parser->slot_pool_ele_cnt = 0UL; 347 : 348 0 : parser->dst = state_dst( parser ); 349 0 : parser->dst_sz = state_size( parser ); 350 0 : parser->dst_cur = 0UL; 351 : 352 0 : parser->entry_avail = 0; 353 0 : parser->group_avail = 0; 354 0 : } 355 : 356 : int 357 : fd_slot_delta_parser_consume( fd_slot_delta_parser_t * parser, 358 : uchar const * buf, 359 : ulong bufsz, 360 0 : fd_slot_delta_parser_advance_result_t * result ) { 361 0 : uchar const * data = buf; 362 0 : ulong data_sz = bufsz; 363 0 : while( data_sz ) { 364 0 : if( FD_UNLIKELY( parser->state==STATE_DONE ) ) break; 365 : 366 0 : ulong consume = fd_ulong_min( data_sz, parser->dst_sz-parser->dst_cur ); 367 : 368 0 : if( FD_LIKELY( parser->dst && consume ) ) { 369 0 : memcpy( parser->dst+parser->dst_cur, data, consume ); 370 0 : } 371 : 372 0 : parser->dst_cur += consume; 373 0 : data += consume; 374 0 : data_sz -= consume; 375 : 376 : #if SLOT_DELTA_PARSER_DEBUG 377 : state_log( parser ); 378 : #endif 379 : 380 0 : if( FD_LIKELY( parser->dst_cur==parser->dst_sz ) ) { 381 0 : int err = state_validate( parser ); 382 0 : if( FD_UNLIKELY( err ) ) { 383 0 : result->bytes_consumed = (ulong)(data - buf); 384 0 : return err; 385 0 : } 386 : 387 0 : state_process( parser ); 388 : 389 0 : parser->dst = state_dst( parser ); 390 0 : parser->dst_sz = state_size( parser ); 391 0 : parser->dst_cur = 0UL; 392 : 393 0 : if( FD_LIKELY( parser->group_avail ) ) { 394 0 : FD_TEST( parser->entry_avail==0 ); 395 0 : parser->group_avail = 0; 396 0 : result->entry = NULL; 397 0 : result->group.blockhash = parser->entry->blockhash; 398 0 : result->group.txnhash_offset = parser->txnhash_offset; 399 0 : result->bytes_consumed = (ulong)(data - buf); 400 0 : return FD_SLOT_DELTA_PARSER_ADVANCE_GROUP; 401 0 : } else if( FD_LIKELY( parser->entry_avail ) ) { 402 0 : FD_TEST( parser->group_avail==0 ); 403 0 : parser->entry_avail = 0; 404 0 : result->entry = parser->entry; 405 0 : result->bytes_consumed = (ulong)(data - buf); 406 0 : return FD_SLOT_DELTA_PARSER_ADVANCE_ENTRY; 407 0 : } 408 0 : } 409 0 : } 410 : 411 0 : 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 0 : result->bytes_consumed = (ulong)(data - buf); 418 0 : return parser->state==STATE_DONE ? FD_SLOT_DELTA_PARSER_ADVANCE_DONE : FD_SLOT_DELTA_PARSER_ADVANCE_AGAIN; 419 0 : } 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 : }