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 : return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES; 123 3 : } 124 33 : break; 125 57 : case STATE_SLOT_DELTA_SLOT: { 126 57 : ulong slot_idx = slot_set_idx_query_const( parser->slot_set, &parser->entry->slot, ULONG_MAX, parser->slot_pool ); 127 : /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/snapshot_bank_utils.rs#L558 */ 128 57 : if( FD_UNLIKELY( slot_idx!=ULONG_MAX ) ) return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_HASH_MULTIPLE_ENTRIES; 129 : 130 54 : if( FD_UNLIKELY( parser->slot_pool_ele_cnt>=FD_SLOT_DELTA_MAX_ENTRIES ) ) { 131 : /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/snapshot_bank_utils.rs#L535 */ 132 0 : return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_TOO_MANY_ENTRIES; 133 0 : } 134 : 135 54 : fd_slot_entry_t * slot_entry = &parser->slot_pool[ parser->slot_pool_ele_cnt++ ]; 136 54 : slot_entry->slot = parser->entry->slot; 137 54 : slot_set_ele_insert( parser->slot_set, slot_entry, parser->slot_pool ); 138 54 : break; 139 54 : } 140 54 : case STATE_SLOT_DELTA_IS_ROOT: 141 54 : if( FD_UNLIKELY( !parser->is_root) ) { 142 : /* https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/snapshot_bank_utils.rs#L545 */ 143 3 : return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_SLOT_IS_NOT_ROOT; 144 3 : } 145 51 : break; 146 663 : default: break; 147 810 : } 148 : 149 801 : return 0; 150 810 : } 151 : 152 : static inline void 153 132 : loop( fd_slot_delta_parser_t * parser ) { 154 132 : if( FD_LIKELY( parser->cache_status_len ) ) { 155 66 : parser->state = STATE_CACHE_STATUS_KEY_SLICE; 156 66 : } else if( FD_LIKELY( parser->slot_delta_status_len ) ) { 157 15 : parser->state = STATE_STATUS_BLOCKHASH; 158 51 : } else if( FD_LIKELY( parser->len ) ) { 159 24 : parser->state = STATE_SLOT_DELTA_SLOT; 160 27 : } else { 161 27 : parser->state = STATE_DONE; 162 27 : } 163 132 : } 164 : 165 : static inline void 166 108 : result_loop( fd_slot_delta_parser_t * parser ) { 167 108 : parser->entry_avail = 1; 168 108 : loop( parser ); 169 108 : } 170 : 171 : static inline void 172 801 : state_process( fd_slot_delta_parser_t * parser ) { 173 801 : FD_TEST( parser->state!=STATE_DONE ); 174 : 175 801 : switch( parser->state ) { 176 33 : case STATE_SLOT_DELTAS_LEN: 177 33 : parser->state = STATE_SLOT_DELTA_SLOT; 178 33 : break; 179 54 : case STATE_SLOT_DELTA_SLOT: 180 54 : parser->state = STATE_SLOT_DELTA_IS_ROOT; 181 54 : parser->len--; 182 54 : break; 183 51 : case STATE_SLOT_DELTA_IS_ROOT: 184 51 : parser->state = STATE_SLOT_DELTA_STATUS_LEN; 185 51 : break; 186 51 : case STATE_SLOT_DELTA_STATUS_LEN: 187 51 : if( FD_UNLIKELY( !parser->slot_delta_status_len ) ) loop( parser ); 188 42 : else parser->state = STATE_STATUS_BLOCKHASH; 189 51 : break; 190 57 : case STATE_STATUS_BLOCKHASH: 191 57 : parser->state = STATE_STATUS_TXN_IDX; 192 57 : parser->slot_delta_status_len--; 193 57 : break; 194 57 : case STATE_STATUS_TXN_IDX: 195 57 : parser->state = STATE_CACHE_STATUS_LEN; 196 57 : parser->group_avail = 1; 197 57 : break; 198 57 : case STATE_CACHE_STATUS_LEN: 199 57 : if( FD_UNLIKELY( !parser->cache_status_len ) ) loop( parser ); 200 42 : else parser->state = STATE_CACHE_STATUS_KEY_SLICE; 201 57 : break; 202 108 : case STATE_CACHE_STATUS_KEY_SLICE: 203 108 : parser->state = STATE_CACHE_STATUS_RESULT; 204 108 : parser->cache_status_len--; 205 108 : break; 206 108 : case STATE_CACHE_STATUS_RESULT: 207 108 : if( FD_LIKELY( !parser->error_discriminant ) ) { 208 27 : parser->entry->result = 0; 209 27 : result_loop( parser ); 210 27 : } 211 81 : else { 212 81 : parser->state = STATE_CACHE_STATUS_RESULT_ERR; 213 81 : } 214 108 : break; 215 81 : case STATE_CACHE_STATUS_RESULT_ERR: 216 81 : if( FD_UNLIKELY( parser->error_discriminant==8U ) ) { 217 45 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX; 218 45 : } else if( FD_UNLIKELY( parser->error_discriminant==30U || parser->error_discriminant==31U || parser->error_discriminant==35U ) ) { 219 18 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_IDX; 220 18 : } else { 221 18 : parser->entry->result = (uchar)parser->error_discriminant; 222 18 : result_loop( parser ); 223 18 : } 224 81 : break; 225 45 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_IDX: 226 45 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR; 227 45 : break; 228 45 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR: 229 45 : if( FD_UNLIKELY( parser->error_discriminant==25U ) ) { 230 18 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM; 231 27 : } else if( FD_UNLIKELY( parser->error_discriminant==44U ) ) { 232 9 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN; 233 18 : } else { 234 18 : parser->entry->result = (uchar)parser->error_discriminant; 235 18 : result_loop( parser ); 236 18 : } 237 45 : break; 238 18 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM: 239 18 : parser->entry->result = (uchar)parser->error_discriminant; 240 18 : result_loop( parser ); 241 18 : break; 242 9 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_LEN: 243 9 : parser->state = STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR; 244 9 : break; 245 9 : case STATE_CACHE_STATUS_RESULT_ERR_INSTR_ERR_CUSTOM_BORSH_ERR: 246 9 : parser->entry->result = (uchar)parser->error_discriminant; 247 9 : result_loop( parser ); 248 9 : break; 249 18 : case STATE_CACHE_STATUS_RESULT_ERR_IDX: 250 18 : parser->entry->result = (uchar)parser->error; 251 18 : result_loop( parser ); 252 18 : break; 253 0 : default: FD_LOG_ERR(( "unknown state %d", parser->state )); 254 801 : } 255 801 : } 256 : 257 : FD_FN_CONST ulong 258 6 : fd_slot_delta_parser_align( void ) { 259 6 : return fd_ulong_max( alignof(fd_slot_delta_parser_t), slot_set_align() ); 260 6 : } 261 : 262 : FD_FN_CONST ulong 263 3 : fd_slot_delta_parser_footprint( void ) { 264 3 : ulong l = FD_LAYOUT_INIT; 265 3 : l = FD_LAYOUT_APPEND( l, alignof(fd_slot_delta_parser_t), sizeof(fd_slot_delta_parser_t) ); 266 3 : l = FD_LAYOUT_APPEND( l, slot_pool_align(), slot_pool_footprint( FD_SLOT_DELTA_MAX_ENTRIES ) ); 267 3 : l = FD_LAYOUT_APPEND( l, slot_set_align(), slot_set_footprint( FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES ) ); 268 3 : return FD_LAYOUT_FINI( l, alignof(fd_slot_delta_parser_t) ); 269 3 : } 270 : 271 : void * 272 3 : fd_slot_delta_parser_new( void * shmem ) { 273 3 : if( FD_UNLIKELY( !shmem ) ) { 274 0 : FD_LOG_WARNING(( "NULL shmem" )); 275 0 : return NULL; 276 0 : } 277 : 278 3 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_slot_delta_parser_align() ) ) ) { 279 0 : FD_LOG_WARNING(( "unaligned shmem" )); 280 0 : return NULL; 281 0 : } 282 : 283 3 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 284 3 : fd_slot_delta_parser_t * parser = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_slot_delta_parser_t), sizeof(fd_slot_delta_parser_t) ); 285 3 : void * slot_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, slot_pool_align(), slot_pool_footprint( FD_SLOT_DELTA_MAX_ENTRIES ) ); 286 3 : void * slot_set_mem = FD_SCRATCH_ALLOC_APPEND( l, slot_set_align(), slot_set_footprint( FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES ) ); 287 : 288 3 : parser->slot_pool = slot_pool_join( slot_pool_new( slot_pool_mem, FD_SLOT_DELTA_MAX_ENTRIES ) ); 289 3 : FD_TEST( parser->slot_pool ); 290 : 291 3 : parser->slot_set = slot_set_join( slot_set_new( slot_set_mem, FD_SLOT_DELTA_PARSER_SLOT_SET_MAX_ENTRIES, 1UL ) ); 292 3 : FD_TEST( parser->slot_set ); 293 : 294 903 : for( ulong i=0UL; i<slot_pool_max( parser->slot_pool ); i++ ) { 295 900 : fd_slot_entry_t * slot_entry = &parser->slot_pool[ i ]; 296 900 : slot_entry->slot = ULONG_MAX; 297 900 : } 298 : 299 3 : parser->entry_avail = 0; 300 3 : parser->group_avail = 0; 301 3 : parser->slot_pool_ele_cnt = 0UL; 302 3 : parser->state = STATE_DONE; 303 : 304 3 : return parser; 305 3 : } 306 : 307 : fd_slot_delta_parser_t * 308 3 : fd_slot_delta_parser_join( void * shmem ) { 309 3 : return shmem; 310 3 : } 311 : 312 : void * 313 3 : fd_slot_delta_parser_leave( fd_slot_delta_parser_t * parser ) { 314 3 : return (void *)parser; 315 3 : } 316 : 317 : void * 318 3 : fd_slot_delta_parser_delete( void * shmem ) { 319 3 : return shmem; 320 3 : } 321 : 322 : void 323 36 : fd_slot_delta_parser_init( fd_slot_delta_parser_t * parser ) { 324 36 : parser->state = STATE_SLOT_DELTAS_LEN; 325 36 : parser->len = 0UL; 326 36 : parser->is_root = 0; 327 : 328 36 : parser->slot_delta_status_len = 0UL; 329 36 : parser->cache_status_len = 0UL; 330 36 : parser->borsh_io_error_len = 0UL; 331 36 : parser->error_discriminant = 0U; 332 : 333 90 : for( ulong i=0UL; i<parser->slot_pool_ele_cnt; i++ ) { 334 54 : fd_slot_entry_t * slot_entry = &parser->slot_pool[ i ]; 335 54 : slot_set_ele_remove_fast( parser->slot_set, slot_entry, parser->slot_pool ); 336 54 : slot_entry->slot = ULONG_MAX; 337 54 : } 338 : 339 36 : parser->slot_pool_ele_cnt = 0UL; 340 : 341 36 : parser->dst = state_dst( parser ); 342 36 : parser->dst_sz = state_size( parser ); 343 36 : parser->dst_cur = 0UL; 344 : 345 36 : parser->entry_avail = 0; 346 36 : parser->group_avail = 0; 347 36 : } 348 : 349 : int 350 : fd_slot_delta_parser_consume( fd_slot_delta_parser_t * parser, 351 : uchar const * buf, 352 : ulong bufsz, 353 180 : fd_slot_delta_parser_advance_result_t * result ) { 354 180 : uchar const * data = buf; 355 180 : ulong data_sz = bufsz; 356 816 : while( data_sz ) { 357 810 : if( FD_UNLIKELY( parser->state==STATE_DONE ) ) break; 358 : 359 810 : ulong consume = fd_ulong_min( data_sz, parser->dst_sz-parser->dst_cur ); 360 : 361 810 : if( FD_LIKELY( parser->dst && consume ) ) { 362 756 : memcpy( parser->dst+parser->dst_cur, data, consume ); 363 756 : } 364 : 365 810 : parser->dst_cur += consume; 366 810 : data += consume; 367 810 : data_sz -= consume; 368 : 369 : #if SLOT_DELTA_PARSER_DEBUG 370 : state_log( parser ); 371 : #endif 372 : 373 810 : if( FD_LIKELY( parser->dst_cur==parser->dst_sz ) ) { 374 810 : int err = state_validate( parser ); 375 810 : if( FD_UNLIKELY( err ) ) { 376 9 : result->bytes_consumed = (ulong)(data - buf); 377 9 : return err; 378 9 : } 379 : 380 801 : state_process( parser ); 381 : 382 801 : parser->dst = state_dst( parser ); 383 801 : parser->dst_sz = state_size( parser ); 384 801 : parser->dst_cur = 0UL; 385 : 386 801 : if( FD_LIKELY( parser->group_avail ) ) { 387 57 : FD_TEST( parser->entry_avail==0 ); 388 57 : parser->group_avail = 0; 389 57 : result->entry = NULL; 390 57 : result->group.blockhash = parser->entry->blockhash; 391 57 : result->group.txnhash_offset = parser->txnhash_offset; 392 57 : result->bytes_consumed = (ulong)(data - buf); 393 57 : return FD_SLOT_DELTA_PARSER_ADVANCE_GROUP; 394 744 : } else if( FD_LIKELY( parser->entry_avail ) ) { 395 108 : FD_TEST( parser->group_avail==0 ); 396 108 : parser->entry_avail = 0; 397 108 : result->entry = parser->entry; 398 108 : result->bytes_consumed = (ulong)(data - buf); 399 108 : return FD_SLOT_DELTA_PARSER_ADVANCE_ENTRY; 400 108 : } 401 801 : } 402 810 : } 403 : 404 6 : if( FD_UNLIKELY( data_sz ) ) { 405 0 : FD_LOG_WARNING(( "excess data in buffer" )); 406 0 : result->bytes_consumed = (ulong)(data - buf); 407 0 : return FD_SLOT_DELTA_PARSER_ADVANCE_ERROR_EXCESS_DATA_IN_BUFFER; 408 0 : } 409 : 410 6 : result->bytes_consumed = (ulong)(data - buf); 411 6 : return parser->state==STATE_DONE ? FD_SLOT_DELTA_PARSER_ADVANCE_DONE : FD_SLOT_DELTA_PARSER_ADVANCE_AGAIN; 412 6 : } 413 : 414 : fd_slot_delta_slot_set_t 415 0 : fd_slot_delta_parser_slot_set( fd_slot_delta_parser_t * parser ) { 416 0 : return (fd_slot_delta_slot_set_t){ 417 0 : .map = parser->slot_set, 418 0 : .pool = parser->slot_pool, 419 0 : .ele_cnt = parser->slot_pool_ele_cnt 420 0 : }; 421 0 : }