Line data Source code
1 : #include "fd_votor_hist.h" 2 : 3 : /* rec_sz is the wire size of a record with these flags */ 4 : 5 : FD_FN_CONST static inline ulong 6 0 : rec_sz( uchar flags ) { 7 0 : return FD_VOTOR_HIST_REC_MIN_SZ + fd_ulong_if( flags & FD_VOTOR_HIST_FLAG_VOTED_NOTAR, sizeof(fd_block_hash_t), 0UL ); 8 0 : } 9 : 10 : /* hist_ok checks the rules both fd_votor_hist_ser and fd_votor_hist_de 11 : enforce. */ 12 : 13 : static int 14 0 : hist_ok( fd_votor_hist_t const * self ) { 15 0 : if( FD_UNLIKELY( self->rec_cnt>FD_VOTOR_HIST_MAX ) ) return 0; 16 0 : if( FD_UNLIKELY( self->anchor==ULONG_MAX ) ) return 0; 17 0 : ulong first = fd_votor_hist_first_slot( self->anchor ); 18 0 : ulong prev = ULONG_MAX; 19 0 : for( ulong i=0UL; i<self->rec_cnt; i++ ) { 20 0 : fd_votor_hist_rec_t const * rec = &self->rec[ i ]; 21 0 : if( FD_UNLIKELY( rec->slot<first ) ) return 0; 22 0 : if( FD_UNLIKELY( i && rec->slot<=prev ) ) return 0; 23 0 : if( FD_UNLIKELY( rec->flags & ~FD_VOTOR_HIST_FLAG_MASK ) ) return 0; 24 0 : if( FD_UNLIKELY( !( rec->flags & FD_VOTOR_HIST_FLAG_VOTED ) ) ) return 0; 25 0 : prev = rec->slot; 26 0 : } 27 0 : return 1; 28 0 : } 29 : 30 : int 31 : fd_votor_hist_ser( fd_votor_hist_t const * self, 32 : uchar * buf, 33 : ulong buf_max, 34 0 : ulong * out_sz ) { 35 0 : if( FD_UNLIKELY( !hist_ok( self ) ) ) return -1; 36 : 37 0 : ulong sz = FD_VOTOR_HIST_HDR_SZ; 38 0 : for( ulong i=0UL; i<self->rec_cnt; i++ ) sz += rec_sz( self->rec[ i ].flags ); 39 0 : if( FD_UNLIKELY( sz>buf_max ) ) return -1; 40 : 41 0 : ulong off = 0UL; 42 0 : FD_STORE( ulong, buf+off, self->anchor ); off += sizeof(ulong); 43 0 : FD_STORE( ulong, buf+off, self->last_leader_slot ); off += sizeof(ulong); 44 0 : FD_STORE( ulong, buf+off, self->vote_bound ); off += sizeof(ulong); 45 0 : FD_STORE( ushort, buf+off, (ushort)self->rec_cnt ); off += sizeof(ushort); 46 0 : for( ulong i=0UL; i<self->rec_cnt; i++ ) { 47 0 : fd_votor_hist_rec_t const * rec = &self->rec[ i ]; 48 0 : FD_STORE( ulong, buf+off, rec->slot ); off += sizeof(ulong); 49 0 : buf[ off ] = rec->flags; off += sizeof(uchar); 50 0 : if( rec->flags & FD_VOTOR_HIST_FLAG_VOTED_NOTAR ) { fd_memcpy( buf+off, &rec->notar_hash, sizeof(fd_block_hash_t) ); off += sizeof(fd_block_hash_t); } 51 0 : } 52 : 53 0 : *out_sz = off; 54 0 : return 0; 55 0 : } 56 : 57 : int 58 : fd_votor_hist_de( uchar const * buf, 59 : ulong buf_sz, 60 0 : fd_votor_hist_t * out ) { 61 0 : if( FD_UNLIKELY( buf_sz<FD_VOTOR_HIST_HDR_SZ ) ) return -1; 62 : 63 0 : fd_votor_hist_t hist[1]; 64 0 : fd_memset( hist, 0, sizeof(fd_votor_hist_t) ); 65 : 66 0 : ulong off = 0UL; 67 0 : hist->anchor = FD_LOAD( ulong, buf+off ); off += sizeof(ulong); 68 0 : hist->last_leader_slot = FD_LOAD( ulong, buf+off ); off += sizeof(ulong); 69 0 : hist->vote_bound = FD_LOAD( ulong, buf+off ); off += sizeof(ulong); 70 0 : hist->rec_cnt = FD_LOAD( ushort, buf+off ); off += sizeof(ushort); 71 0 : if( FD_UNLIKELY( hist->rec_cnt>FD_VOTOR_HIST_MAX ) ) return -1; 72 : 73 0 : for( ulong i=0UL; i<hist->rec_cnt; i++ ) { 74 0 : fd_votor_hist_rec_t * rec = &hist->rec[ i ]; 75 0 : if( FD_UNLIKELY( buf_sz-off<FD_VOTOR_HIST_REC_MIN_SZ ) ) return -1; 76 0 : rec->slot = FD_LOAD( ulong, buf+off ); off += sizeof(ulong); 77 0 : rec->flags = buf[ off ]; off += sizeof(uchar); 78 0 : if( rec->flags & FD_VOTOR_HIST_FLAG_VOTED_NOTAR ) { 79 0 : if( FD_UNLIKELY( buf_sz-off<sizeof(fd_block_hash_t) ) ) return -1; 80 0 : fd_memcpy( &rec->notar_hash, buf+off, sizeof(fd_block_hash_t) ); off += sizeof(fd_block_hash_t); 81 0 : } 82 0 : } 83 0 : if( FD_UNLIKELY( off!=buf_sz ) ) return -1; /* trailing bytes */ 84 0 : if( FD_UNLIKELY( !hist_ok( hist ) ) ) return -1; 85 : 86 0 : *out = *hist; 87 0 : return 0; 88 0 : }