Line data Source code
1 : #include "fd_types.h"
2 : #ifndef SOURCE_fd_src_flamenco_types_fd_types_c
3 : #error "fd_types_custom.c is part of the fd_types.c compile uint"
4 : #endif /* !SOURCE_fd_src_flamenco_types_fd_types_c */
5 :
6 : #include <stdio.h>
7 :
8 : int
9 : fd_flamenco_txn_decode( fd_flamenco_txn_t * self,
10 3 : fd_bincode_decode_ctx_t * ctx ) {
11 3 : static FD_TL fd_txn_parse_counters_t counters[1];
12 3 : ulong bufsz = (ulong)ctx->dataend - (ulong)ctx->data;
13 3 : ulong sz;
14 3 : ulong res = fd_txn_parse_core( ctx->data, bufsz, self->txn, counters, &sz );
15 3 : if( FD_UNLIKELY( !res ) ) {
16 : /* TODO: Remove this debug print in prod */
17 0 : FD_LOG_DEBUG(( "Failed to decode txn (fd_txn.c:%lu)",
18 0 : counters->failure_ring[ counters->failure_cnt % FD_TXN_PARSE_COUNTERS_RING_SZ ] ));
19 0 : return -1000001;
20 0 : }
21 3 : fd_memcpy( self->raw, ctx->data, sz );
22 3 : self->raw_sz = sz;
23 3 : ctx->data = (void *)( (ulong)ctx->data + sz );
24 3 : return 0;
25 3 : }
26 :
27 : int
28 6 : fd_flamenco_txn_decode_preflight( fd_bincode_decode_ctx_t * ctx ) {
29 6 : ulong bufsz = (ulong)ctx->dataend - (ulong)ctx->data;
30 6 : fd_flamenco_txn_t self;
31 6 : ulong sz;
32 6 : ulong res = fd_txn_parse_core( ctx->data, bufsz, self.txn, NULL, &sz );
33 6 : if( FD_UNLIKELY( !res ) ) {
34 0 : return -1000001;
35 0 : }
36 6 : ctx->data = (void *)( (ulong)ctx->data + sz );
37 6 : return 0;
38 6 : }
39 :
40 : void
41 : fd_flamenco_txn_decode_unsafe( fd_flamenco_txn_t * self,
42 6 : fd_bincode_decode_ctx_t * ctx ) {
43 6 : static FD_TL fd_txn_parse_counters_t counters[1];
44 6 : ulong bufsz = (ulong)ctx->dataend - (ulong)ctx->data;
45 6 : ulong sz;
46 6 : ulong res = fd_txn_parse_core( ctx->data, bufsz, self->txn, counters, &sz );
47 6 : if( FD_UNLIKELY( !res ) ) {
48 0 : FD_LOG_ERR(( "Failed to decode txn (fd_txn.c:%lu)",
49 0 : counters->failure_ring[ counters->failure_cnt % FD_TXN_PARSE_COUNTERS_RING_SZ ] ));
50 0 : return;
51 0 : }
52 6 : fd_memcpy( self->raw, ctx->data, sz );
53 6 : self->raw_sz = sz;
54 6 : ctx->data = (void *)( (ulong)ctx->data + sz );
55 6 : }
56 :
57 : void
58 : fd_gossip_ip4_addr_walk( void * w,
59 : fd_gossip_ip4_addr_t const * self,
60 : fd_types_walk_fn_t fun,
61 : char const * name,
62 93 : uint level ) {
63 :
64 93 : char buf[ 16 ];
65 93 : sprintf( buf, FD_IP4_ADDR_FMT, FD_IP4_ADDR_FMT_ARGS( *self ) );
66 93 : fun( w, buf, name, FD_FLAMENCO_TYPE_CSTR, "ip4_addr", level );
67 93 : }
68 :
69 : void
70 : fd_gossip_ip6_addr_walk( void * w,
71 : fd_gossip_ip6_addr_t const * self,
72 : fd_types_walk_fn_t fun,
73 : char const * name,
74 0 : uint level ) {
75 :
76 0 : char buf[ 40 ];
77 0 : sprintf( buf,
78 0 : "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
79 0 : FD_LOG_HEX16_FMT_ARGS( self->us ) );
80 0 : fun( w, buf, name, FD_FLAMENCO_TYPE_CSTR, "ip6_addr", level );
81 0 : }
82 :
83 0 : int fd_tower_sync_decode( fd_tower_sync_t * self, fd_bincode_decode_ctx_t * ctx ) {
84 0 : void const * data = ctx->data;
85 0 : int err = fd_tower_sync_decode_preflight( ctx );
86 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err;
87 0 : ctx->data = data;
88 0 : fd_tower_sync_new( self );
89 0 : fd_tower_sync_decode_unsafe( self, ctx );
90 0 : return FD_BINCODE_SUCCESS;
91 0 : }
92 :
93 1248 : int fd_tower_sync_decode_preflight( fd_bincode_decode_ctx_t * ctx ) {
94 1248 : FD_SCRATCH_SCOPE_BEGIN {
95 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L1054-L1060
96 1248 : fd_compact_tower_sync_t compact_tower_sync[1];
97 1248 : fd_bincode_decode_ctx_t decode_ctx = { .data = ctx->data, .dataend = ctx->dataend, .valloc = fd_scratch_virtual() };
98 : // Try to decode compact_tower_sync to check that lockout offsets don't cause an overflow
99 1248 : int err = fd_compact_tower_sync_decode( compact_tower_sync, &decode_ctx );
100 1248 : if( FD_UNLIKELY( err ) ) return err;
101 285 : ctx->data = decode_ctx.data;
102 :
103 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L1061
104 285 : ulong root = compact_tower_sync->root != ULONG_MAX ? compact_tower_sync->root : 0;
105 285 : for (deq_fd_lockout_offset_t_iter_t iter = deq_fd_lockout_offset_t_iter_init( compact_tower_sync->lockout_offsets );
106 3276 : !deq_fd_lockout_offset_t_iter_done( compact_tower_sync->lockout_offsets, iter );
107 3087 : iter = deq_fd_lockout_offset_t_iter_next( compact_tower_sync->lockout_offsets, iter )) {
108 3087 : const fd_lockout_offset_t * lockout_offset = deq_fd_lockout_offset_t_iter_ele_const( compact_tower_sync->lockout_offsets, iter );
109 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L1066
110 3087 : err = __builtin_uaddl_overflow( root, lockout_offset->offset, &root );
111 3087 : if( FD_UNLIKELY( err ) ) return err;
112 3087 : }
113 189 : return FD_BINCODE_SUCCESS;
114 1248 : } FD_SCRATCH_SCOPE_END;
115 1248 : }
116 :
117 165 : void fd_tower_sync_decode_unsafe( fd_tower_sync_t * self, fd_bincode_decode_ctx_t * ctx ) {
118 165 : self->has_root = 1;
119 165 : fd_bincode_uint64_decode_unsafe( &self->root, ctx );
120 165 : self->has_root = self->root != ULONG_MAX;
121 :
122 165 : ushort lockout_offsets_len;
123 165 : fd_bincode_compact_u16_decode_unsafe( &lockout_offsets_len, ctx );
124 165 : ulong lockout_offsets_max = fd_ulong_max( lockout_offsets_len, 32 );
125 165 : self->lockouts = deq_fd_vote_lockout_t_alloc( ctx->valloc, lockout_offsets_max );
126 :
127 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L1062-L1077
128 165 : ulong last_slot = ((self->root == ULONG_MAX) ? 0 : self->root);
129 2433 : for( ulong i=0; i < lockout_offsets_len; i++ ) {
130 2268 : fd_vote_lockout_t * elem = deq_fd_vote_lockout_t_push_tail_nocopy( self->lockouts );
131 :
132 2268 : fd_lockout_offset_t o;
133 2268 : fd_lockout_offset_decode_unsafe( &o, ctx );
134 :
135 2268 : elem->slot = last_slot + o.offset;
136 2268 : elem->confirmation_count = o.confirmation_count;
137 2268 : last_slot = elem->slot;
138 2268 : }
139 :
140 165 : fd_hash_decode_unsafe( &self->hash, ctx );
141 165 : {
142 165 : uchar o;
143 165 : fd_bincode_bool_decode_unsafe( &o, ctx );
144 165 : self->has_timestamp = !!o;
145 165 : if( o ) {
146 30 : fd_bincode_int64_decode_unsafe( &self->timestamp, ctx );
147 30 : }
148 165 : }
149 165 : fd_hash_decode_unsafe( &self->block_id, ctx );
150 165 : }
151 :
152 0 : int fd_tower_sync_decode_offsets( fd_tower_sync_off_t * self, fd_bincode_decode_ctx_t * ctx ) {
153 0 : FD_LOG_ERR(( "todo"));
154 0 : }
155 :
156 0 : int fd_tower_sync_encode( fd_tower_sync_t const * self, fd_bincode_encode_ctx_t * ctx ) {
157 0 : FD_LOG_ERR(( "todo"));
158 0 : }
159 :
160 0 : int fd_solana_vote_account_decode( fd_solana_vote_account_t * self, fd_bincode_decode_ctx_t * ctx ) {
161 0 : void const * data = ctx->data;
162 0 : int err = fd_solana_vote_account_decode_preflight( ctx );
163 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err;
164 0 : ctx->data = data;
165 0 : fd_solana_vote_account_new( self );
166 0 : fd_solana_vote_account_decode_unsafe( self, ctx );
167 0 : return FD_BINCODE_SUCCESS;
168 0 : }
169 :
170 0 : int fd_solana_vote_account_decode_preflight( fd_bincode_decode_ctx_t * ctx ) {
171 0 : int err;
172 0 : err = fd_bincode_uint64_decode_preflight( ctx );
173 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err;
174 0 : ulong data_len;
175 0 : err = fd_bincode_uint64_decode( &data_len, ctx );
176 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err;
177 0 : if( data_len ) {
178 0 : err = fd_bincode_bytes_decode_preflight( data_len, ctx );
179 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err;
180 0 : }
181 0 : err = fd_bincode_bytes_decode_preflight( 32, ctx );
182 0 : if( FD_UNLIKELY( err ) ) return err;
183 0 : err = fd_bincode_uint8_decode_preflight( ctx );
184 0 : if( FD_UNLIKELY( err ) ) return err;
185 0 : err = fd_bincode_uint64_decode_preflight( ctx );
186 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err;
187 0 : return FD_BINCODE_SUCCESS;
188 0 : }
189 :
190 0 : void fd_solana_vote_account_decode_unsafe( fd_solana_vote_account_t * self, fd_bincode_decode_ctx_t * ctx ) {
191 0 : fd_bincode_uint64_decode_unsafe( &self->lamports, ctx );
192 0 : ulong data_len;
193 0 : fd_bincode_uint64_decode_unsafe( &data_len, ctx );
194 0 : if( data_len ) {
195 0 : FD_SCRATCH_SCOPE_BEGIN {
196 : /* Deserialize content */
197 0 : fd_vote_block_timestamp_t vote_ts;
198 0 : fd_vote_state_versioned_t vs[1];
199 0 : fd_bincode_decode_ctx_t decode =
200 0 : { .data = (uchar *)ctx->data,
201 0 : .dataend = (uchar *)ctx->data + data_len,
202 0 : .valloc = fd_scratch_virtual() };
203 0 : ctx->data = decode.dataend;
204 0 : int decode_err = fd_vote_state_versioned_decode( vs, &decode );
205 0 : if( FD_LIKELY( decode_err==FD_BINCODE_SUCCESS ) ) {
206 0 : switch( vs->discriminant )
207 0 : {
208 0 : case fd_vote_state_versioned_enum_current:
209 0 : vote_ts = vs->inner.current.last_timestamp;
210 0 : self->node_pubkey = vs->inner.current.node_pubkey;
211 0 : break;
212 0 : case fd_vote_state_versioned_enum_v0_23_5:
213 0 : vote_ts = vs->inner.v0_23_5.last_timestamp;
214 0 : self->node_pubkey = vs->inner.v0_23_5.node_pubkey;
215 0 : break;
216 0 : case fd_vote_state_versioned_enum_v1_14_11:
217 0 : vote_ts = vs->inner.v1_14_11.last_timestamp;
218 0 : self->node_pubkey = vs->inner.v1_14_11.node_pubkey;
219 0 : break;
220 0 : default:
221 0 : __builtin_unreachable();
222 0 : }
223 0 : self->last_timestamp_ts = vote_ts.timestamp;
224 0 : self->last_timestamp_slot = vote_ts.slot;
225 0 : } else {
226 0 : FD_LOG_DEBUG(( "fd_vote_state_versioned_decode failed (%d)", decode_err ));
227 0 : self->last_timestamp_ts = 0;
228 0 : self->last_timestamp_slot = 0;
229 0 : fd_memset( &self->node_pubkey, 0UL, sizeof(fd_pubkey_t) );
230 0 : }
231 0 : } FD_SCRATCH_SCOPE_END;
232 0 : } else {
233 0 : self->last_timestamp_ts = 0;
234 0 : self->last_timestamp_slot = 0;
235 0 : fd_memset( &self->node_pubkey, 0UL, sizeof(fd_pubkey_t) );
236 0 : }
237 :
238 0 : fd_pubkey_decode_unsafe( &self->owner, ctx );
239 0 : fd_bincode_uint8_decode_unsafe( &self->executable, ctx );
240 0 : fd_bincode_uint64_decode_unsafe( &self->rent_epoch, ctx );
241 0 : }
242 :
243 0 : void fd_solana_vote_account_new(fd_solana_vote_account_t * self) {
244 0 : fd_memset( self, 0, sizeof(fd_solana_vote_account_t) );
245 0 : fd_pubkey_new( &self->node_pubkey );
246 0 : fd_pubkey_new( &self->owner );
247 0 : }
248 :
249 0 : void fd_solana_vote_account_destroy( fd_solana_vote_account_t * self, fd_bincode_destroy_ctx_t * ctx ) {
250 0 : fd_pubkey_destroy( &self->node_pubkey, ctx );
251 0 : fd_pubkey_destroy( &self->owner, ctx );
252 0 : }
253 :
254 0 : ulong fd_solana_vote_account_footprint( void ){ return FD_SOLANA_VOTE_ACCOUNT_FOOTPRINT; }
255 0 : ulong fd_solana_vote_account_align( void ){ return FD_SOLANA_VOTE_ACCOUNT_ALIGN; }
256 :
257 0 : void fd_solana_vote_account_walk( void * w, fd_solana_vote_account_t const * self, fd_types_walk_fn_t fun, const char *name, uint level ) {
258 0 : fun( w, self, name, FD_FLAMENCO_TYPE_MAP, "fd_solana_vote_account", level++ );
259 0 : fun( w, &self->lamports, "lamports", FD_FLAMENCO_TYPE_ULONG, "ulong", level );
260 0 : fd_pubkey_walk( w, &self->node_pubkey, fun, "node_pubkey", level );
261 0 : fun( w, &self->last_timestamp_ts, "last_timestamp_ts", FD_FLAMENCO_TYPE_ULONG, "ulong", level );
262 0 : fun( w, &self->last_timestamp_slot, "last_timestamp_slot", FD_FLAMENCO_TYPE_ULONG, "ulong", level );
263 0 : fd_pubkey_walk( w, &self->owner, fun, "owner", level );
264 0 : fun( w, &self->executable, "executable", FD_FLAMENCO_TYPE_UCHAR, "uchar", level );
265 0 : fun( w, &self->rent_epoch, "rent_epoch", FD_FLAMENCO_TYPE_ULONG, "ulong", level );
266 0 : fun( w, self, name, FD_FLAMENCO_TYPE_MAP_END, "fd_solana_vote_account", level-- );
267 0 : }
268 :
269 0 : ulong fd_solana_vote_account_size( fd_solana_vote_account_t const * self ) {
270 0 : ulong size = 0;
271 0 : size += sizeof(ulong);
272 0 : fd_pubkey_t null_key = {0};
273 0 : size += sizeof(ulong);
274 0 : if( memcmp( self->node_pubkey.key, null_key.key, sizeof(fd_pubkey_t) ) ) {
275 0 : fd_vote_state_versioned_t vote_state;
276 0 : fd_vote_state_versioned_new_disc( &vote_state, fd_vote_state_versioned_enum_current );
277 0 : vote_state.inner.current.node_pubkey = self->node_pubkey;
278 0 : vote_state.inner.current.last_timestamp = (fd_vote_block_timestamp_t){
279 0 : .timestamp = self->last_timestamp_ts,
280 0 : .slot = self->last_timestamp_slot
281 0 : };
282 0 : size += fd_vote_state_versioned_size( &vote_state );
283 0 : }
284 0 : size += fd_pubkey_size( &self->owner );
285 0 : size += sizeof(char);
286 0 : size += sizeof(ulong);
287 0 : return size;
288 0 : }
289 :
290 0 : int fd_solana_vote_account_encode( fd_solana_vote_account_t const * self, fd_bincode_encode_ctx_t * ctx ) {
291 0 : int err;
292 0 : err = fd_bincode_uint64_encode( self->lamports, ctx );
293 0 : if( FD_UNLIKELY( err ) ) return err;
294 0 : fd_pubkey_t null_key = {0};
295 0 : if( memcmp( self->node_pubkey.key, null_key.key, sizeof(fd_pubkey_t) ) ) {
296 0 : fd_vote_state_versioned_t vote_state;
297 0 : fd_vote_state_versioned_new_disc( &vote_state, fd_vote_state_versioned_enum_current );
298 0 : vote_state.inner.current.node_pubkey = self->node_pubkey;
299 0 : vote_state.inner.current.last_timestamp = (fd_vote_block_timestamp_t){
300 0 : .timestamp = self->last_timestamp_ts,
301 0 : .slot = self->last_timestamp_slot
302 0 : };
303 0 : ulong data_len = fd_vote_state_versioned_size( &vote_state );
304 0 : err = fd_bincode_uint64_encode( data_len, ctx );
305 0 : if( FD_UNLIKELY(err) ) return err;
306 0 : err = fd_vote_state_versioned_encode( &vote_state, ctx );
307 0 : if( FD_UNLIKELY(err) ) return err;
308 0 : } else {
309 0 : err = fd_bincode_uint64_encode( 0UL, ctx );
310 0 : if( FD_UNLIKELY(err) ) return err;
311 0 : }
312 0 : err = fd_pubkey_encode( &self->owner, ctx );
313 0 : if( FD_UNLIKELY( err ) ) return err;
314 0 : err = fd_bincode_uint8_encode( (uchar)(self->executable), ctx );
315 0 : if( FD_UNLIKELY( err ) ) return err;
316 0 : err = fd_bincode_uint64_encode( self->rent_epoch, ctx );
317 0 : if( FD_UNLIKELY( err ) ) return err;
318 0 : return FD_BINCODE_SUCCESS;
319 0 : }
320 :
321 0 : int fd_archive_decode_skip_field( fd_bincode_decode_ctx_t * ctx, ushort tag ) {
322 : /* Extract the meta tag */
323 0 : tag = tag & (ushort)((1<<6)-1);
324 0 : uint len;
325 0 : switch( tag ) {
326 0 : case FD_ARCHIVE_META_CHAR: len = sizeof(uchar); break;
327 0 : case FD_ARCHIVE_META_CHAR32: len = 32; break;
328 0 : case FD_ARCHIVE_META_DOUBLE: len = sizeof(double); break;
329 0 : case FD_ARCHIVE_META_LONG: len = sizeof(long); break;
330 0 : case FD_ARCHIVE_META_UINT: len = sizeof(uint); break;
331 0 : case FD_ARCHIVE_META_UINT128: len = sizeof(uint128); break;
332 0 : case FD_ARCHIVE_META_BOOL: len = 1; break;
333 0 : case FD_ARCHIVE_META_UCHAR: len = sizeof(uchar); break;
334 0 : case FD_ARCHIVE_META_UCHAR32: len = 32; break;
335 0 : case FD_ARCHIVE_META_UCHAR128: len = 128; break;
336 0 : case FD_ARCHIVE_META_UCHAR2048: len = 2048; break;
337 0 : case FD_ARCHIVE_META_ULONG: len = sizeof(ulong); break;
338 0 : case FD_ARCHIVE_META_USHORT: len = sizeof(ushort); break;
339 :
340 0 : case FD_ARCHIVE_META_STRING: {
341 0 : ulong slen;
342 0 : int err = fd_bincode_uint64_decode( &slen, ctx );
343 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err;
344 0 : len = (uint)slen;
345 0 : break;
346 0 : }
347 :
348 0 : case FD_ARCHIVE_META_STRUCT:
349 0 : case FD_ARCHIVE_META_VECTOR:
350 0 : case FD_ARCHIVE_META_DEQUE:
351 0 : case FD_ARCHIVE_META_MAP:
352 0 : case FD_ARCHIVE_META_TREAP:
353 0 : case FD_ARCHIVE_META_OPTION:
354 0 : case FD_ARCHIVE_META_ARRAY: {
355 0 : int err = fd_bincode_uint32_decode( &len, ctx );
356 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err;
357 0 : break;
358 0 : }
359 :
360 0 : default:
361 0 : return FD_BINCODE_ERR_ENCODING;
362 0 : }
363 :
364 0 : uchar * ptr = (uchar *)ctx->data;
365 0 : if ( FD_UNLIKELY((void *)(ptr + len) > ctx->dataend ) )
366 0 : return FD_BINCODE_ERR_UNDERFLOW;
367 0 : ctx->data = ptr + len;
368 0 : return FD_BINCODE_SUCCESS;
369 0 : }
370 :
371 0 : #define REDBLK_T fd_vote_reward_t_mapnode_t
372 : #define REDBLK_NAME fd_vote_reward_t_map
373 : #define REDBLK_IMPL_STYLE 2
374 : #include "../../util/tmpl/fd_redblack.c"
375 : #undef REDBLK_T
376 : #undef REDBLK_NAME
377 0 : long fd_vote_reward_t_map_compare( fd_vote_reward_t_mapnode_t * left, fd_vote_reward_t_mapnode_t * right ) {
378 0 : return memcmp( left->elem.pubkey.uc, right->elem.pubkey.uc, sizeof(right->elem.pubkey) );
379 0 : }
|