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