Line data Source code
1 : #include "fd_types_custom.h" 2 : #include "fd_bincode.h" 3 : #include "fd_types.h" 4 : #include "fd_types_meta.h" 5 : #ifndef SOURCE_fd_src_flamenco_types_fd_types_c 6 : #error "fd_types_custom.c is part of the fd_types.c compile uint" 7 : #endif /* !SOURCE_fd_src_flamenco_types_fd_types_c */ 8 : 9 : #include <stdio.h> 10 : 11 0 : int fd_tower_sync_encode( fd_tower_sync_t const * self, fd_bincode_encode_ctx_t * ctx ) { 12 0 : FD_LOG_ERR(( "todo")); 13 0 : } 14 : 15 : static void fd_hash_decode_inner( void * struct_mem, void * * alloc_mem, fd_bincode_decode_ctx_t * ctx ); 16 : static int fd_hash_decode_footprint_inner( fd_bincode_decode_ctx_t * ctx, ulong * total_sz ); 17 : static void fd_lockout_offset_decode_inner( void * struct_mem, void * * alloc_mem, fd_bincode_decode_ctx_t * ctx ); 18 : static int fd_lockout_offset_decode_footprint_inner( fd_bincode_decode_ctx_t * ctx, ulong * total_sz ); 19 : 20 0 : int fd_tower_sync_decode_footprint_inner( fd_bincode_decode_ctx_t * ctx, ulong * total_sz ) { 21 : /* This is a modified version of fd_compact_tower_sync_decode_footprint_inner() */ 22 0 : int err = 0; 23 0 : if( FD_UNLIKELY( ctx->data>ctx->dataend ) ) { return FD_BINCODE_ERR_OVERFLOW; } 24 0 : err = fd_bincode_uint64_decode_footprint( ctx ); 25 : 26 : /* The first modification is that we want to grab the value fo the root. */ 27 0 : ulong root = 0UL; 28 0 : fd_bincode_decode_ctx_t root_ctx = { .data = (uchar*)ctx->data - sizeof(ulong), .dataend = ctx->data }; 29 0 : if( FD_UNLIKELY( ((ulong)ctx->data)+sizeof(ulong)>(ulong)ctx->dataend ) ) { return FD_BINCODE_ERR_OVERFLOW; } 30 0 : fd_bincode_uint64_decode_unsafe( &root, &root_ctx ); 31 0 : root = root != ULONG_MAX ? root : 0UL; 32 : /* Done with first modification */ 33 : 34 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err; 35 0 : ushort lockout_offsets_len; 36 0 : if( FD_UNLIKELY( ctx->data>=ctx->dataend ) ) { return FD_BINCODE_ERR_OVERFLOW; } 37 0 : err = fd_bincode_compact_u16_decode( &lockout_offsets_len, ctx ); 38 : 39 0 : if( FD_UNLIKELY( err ) ) return err; 40 0 : ulong lockout_offsets_max = fd_ulong_max( lockout_offsets_len, 32 ); 41 0 : *total_sz += deq_fd_lockout_offset_t_align() + deq_fd_lockout_offset_t_footprint( lockout_offsets_max ); 42 : 43 0 : for( ulong i = 0; i < lockout_offsets_len; ++i ) { 44 : 45 0 : uchar const * start_data = ctx->data; 46 0 : err = fd_lockout_offset_decode_footprint_inner( ctx, total_sz ); 47 0 : if( FD_UNLIKELY( err ) ) return err; 48 : 49 : /* The second modification is that we want to grab the lockout offset from 50 : the deque to make sure that we can do a checked add successfully. */ 51 0 : fd_lockout_offset_t lockout_offset = {0}; 52 0 : fd_bincode_decode_ctx_t lockout_ctx = { .data = start_data, .dataend = start_data+sizeof(fd_lockout_offset_t) }; 53 0 : if( FD_UNLIKELY( ctx->data>=ctx->dataend ) ) { return FD_BINCODE_ERR_OVERFLOW; } 54 0 : fd_lockout_offset_decode_inner( &lockout_offset, NULL, &lockout_ctx ); 55 0 : err = __builtin_uaddl_overflow( root, lockout_offset.offset, &root ); 56 0 : if( FD_UNLIKELY( err ) ) { 57 0 : return err; 58 0 : } 59 : /* Done with second modification. */ 60 0 : } 61 : 62 0 : if( FD_UNLIKELY( ctx->data>=ctx->dataend ) ) { return FD_BINCODE_ERR_OVERFLOW; } 63 0 : err = fd_hash_decode_footprint_inner( ctx, total_sz ); 64 0 : if( FD_UNLIKELY( err ) ) return err; 65 0 : { 66 0 : uchar o; 67 0 : if( FD_UNLIKELY( ctx->data>=ctx->dataend ) ) { return FD_BINCODE_ERR_OVERFLOW; } 68 0 : err = fd_bincode_bool_decode( &o, ctx ); 69 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err; 70 0 : if( o ) { 71 0 : if( FD_UNLIKELY( ctx->data>=ctx->dataend ) ) { return FD_BINCODE_ERR_OVERFLOW; } 72 0 : err = fd_bincode_int64_decode_footprint( ctx ); 73 0 : if( FD_UNLIKELY( err!=FD_BINCODE_SUCCESS ) ) return err; 74 0 : } 75 0 : } 76 0 : if( FD_UNLIKELY( ctx->data>=ctx->dataend ) ) { return FD_BINCODE_ERR_OVERFLOW; } 77 0 : err = fd_hash_decode_footprint_inner( ctx, total_sz ); 78 0 : if( FD_UNLIKELY( err ) ) return err; 79 0 : return 0; 80 0 : } 81 : 82 0 : int fd_tower_sync_decode_footprint( fd_bincode_decode_ctx_t * ctx, ulong * total_sz ) { 83 0 : *total_sz += sizeof(fd_tower_sync_t); 84 0 : void const * start_data = ctx->data; 85 0 : int err = fd_tower_sync_decode_footprint_inner( ctx, total_sz ); 86 0 : ctx->data = start_data; 87 0 : return err; 88 0 : } 89 : 90 0 : void fd_tower_sync_decode_inner( void * struct_mem, void * * alloc_mem, fd_bincode_decode_ctx_t * ctx ) { 91 0 : fd_tower_sync_t * self = (fd_tower_sync_t *)struct_mem; 92 0 : self->has_root = 1; 93 0 : fd_bincode_uint64_decode_unsafe( &self->root, ctx ); 94 0 : self->has_root = self->root != ULONG_MAX; 95 : 96 0 : ushort lockout_offsets_len; 97 0 : fd_bincode_compact_u16_decode_unsafe( &lockout_offsets_len, ctx ); 98 0 : ulong lockout_offsets_max = fd_ulong_max( lockout_offsets_len, 32 ); 99 0 : self->lockouts = deq_fd_vote_lockout_t_join_new( alloc_mem, lockout_offsets_max ); 100 : 101 : /* NOTE: Agave does a a checked add on the sum of the root with all of the 102 : lockout offsets in their custom deserializer for tower sync votes. If the 103 : checked add is violated (this should never happen), the deocder will 104 : return NULL. */ 105 : 106 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L1062-L1077 107 0 : ulong last_slot = ((self->root == ULONG_MAX) ? 0 : self->root); 108 0 : for( ulong i=0; i < lockout_offsets_len; i++ ) { 109 0 : fd_vote_lockout_t * elem = deq_fd_vote_lockout_t_push_tail_nocopy( self->lockouts ); 110 : 111 0 : fd_lockout_offset_t o; 112 0 : fd_lockout_offset_decode_inner( &o, alloc_mem, ctx ); 113 : 114 0 : elem->slot = last_slot + o.offset; 115 0 : elem->confirmation_count = o.confirmation_count; 116 0 : last_slot = elem->slot; 117 0 : } 118 : 119 0 : fd_hash_decode_inner( &self->hash, alloc_mem, ctx ); 120 0 : { 121 0 : uchar o; 122 0 : fd_bincode_bool_decode_unsafe( &o, ctx ); 123 0 : self->has_timestamp = !!o; 124 0 : if( o ) { 125 0 : fd_bincode_int64_decode_unsafe( &self->timestamp, ctx ); 126 0 : } 127 0 : } 128 0 : fd_hash_decode_inner( &self->block_id, alloc_mem, ctx ); 129 0 : } 130 : 131 0 : void * fd_tower_sync_decode( void * mem, fd_bincode_decode_ctx_t * ctx ) { 132 0 : fd_tower_sync_t * self = (fd_tower_sync_t *)mem; 133 0 : fd_tower_sync_new( self ); 134 0 : void * alloc_region = (uchar *)mem + sizeof(fd_tower_sync_t); 135 0 : void * * alloc_mem = &alloc_region; 136 0 : fd_tower_sync_decode_inner( mem, alloc_mem, ctx ); 137 0 : return self; 138 0 : } 139 : 140 0 : void fd_tower_sync_decode_inner_global( void * struct_mem, void * * alloc_mem, fd_bincode_decode_ctx_t * ctx ) { 141 0 : FD_LOG_ERR(("TODO: Implement")); 142 0 : } 143 : 144 : // https://github.com/serde-rs/serde/blob/49d098debdf8b5c38bfb6868f455c6ce542c422c/serde/src/de/impls.rs#L2374 145 : // 146 : // During the call to Duration::new(...), it normalizes the seconds and nanoseconds automatically. We need to 147 : // match this behavior correctly 148 : // 149 : void 150 0 : fd_rust_duration_normalize ( fd_rust_duration_t * self ) { 151 0 : if( self->nanoseconds < 1000000000U ) 152 0 : return; 153 0 : uint secs = self->nanoseconds/1000000000U; 154 0 : self->seconds += secs; 155 0 : self->nanoseconds -= secs * 1000000000U; 156 0 : } 157 : 158 : // https://github.com/serde-rs/serde/blob/49d098debdf8b5c38bfb6868f455c6ce542c422c/serde/src/de/impls.rs#L2203 159 : // 160 : // There is an overflow check at line 2373 that turns an overflow into an encoding error 161 : // 162 : int 163 0 : fd_rust_duration_footprint_validator ( fd_bincode_decode_ctx_t * ctx ) { 164 0 : fd_rust_duration_t *d = (fd_rust_duration_t *) ctx->data; 165 0 : if( d->nanoseconds < 1000000000U ) 166 0 : return FD_BINCODE_SUCCESS; 167 0 : ulong out; 168 0 : if( __builtin_uaddl_overflow( d->seconds, d->nanoseconds/1000000000U, &out ) ) 169 0 : return FD_BINCODE_ERR_ENCODING; 170 0 : return FD_BINCODE_SUCCESS; 171 0 : } 172 : 173 0 : #define REDBLK_T fd_stake_weight_t_mapnode_t 174 : #define REDBLK_NAME fd_stake_weight_t_map 175 : #define REDBLK_IMPL_STYLE 2 176 : #include "../../util/tmpl/fd_redblack.c" 177 0 : long fd_stake_weight_t_map_compare( fd_stake_weight_t_mapnode_t * left, fd_stake_weight_t_mapnode_t * right ) { 178 0 : return memcmp( left->elem.key.uc, right->elem.key.uc, sizeof(right->elem.key) ); 179 0 : }