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 : }
|