Line data Source code
1 : #include "fd_rserve.h" 2 : #include "fd_repair.h" 3 : #include "../../ballet/sha256/fd_sha256.h" 4 : 5 : ulong 6 0 : fd_rserve_footprint( ulong ping_cache_entries ) { 7 0 : if( FD_UNLIKELY( !ping_cache_entries ) ) return 0UL; 8 : 9 0 : ulong ping_max = fd_ulong_pow2_up( ping_cache_entries ); 10 : 11 0 : ulong l = FD_LAYOUT_INIT; 12 0 : l = FD_LAYOUT_APPEND( l, alignof(fd_rserve_t), sizeof(fd_rserve_t) ); 13 0 : l = FD_LAYOUT_APPEND( l, ping_pool_align(), ping_pool_footprint( ping_max ) ); 14 0 : l = FD_LAYOUT_APPEND( l, ping_map_align(), ping_map_footprint( ping_map_chain_cnt_est( ping_max ) ) ); 15 0 : l = FD_LAYOUT_APPEND( l, ping_dlist_align(), ping_dlist_footprint() ); 16 0 : return FD_LAYOUT_FINI( l, fd_rserve_align() ); 17 0 : } 18 : 19 : void * 20 : fd_rserve_new( void * shmem, 21 : ulong ping_cache_entries, 22 0 : ulong seed ) { 23 0 : if( FD_UNLIKELY( !shmem ) ) { 24 0 : FD_LOG_WARNING(( "NULL mem" )); 25 0 : return NULL; 26 0 : } 27 : 28 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_rserve_align() ) ) ) { 29 0 : FD_LOG_WARNING(( "misaligned mem" )); 30 0 : return NULL; 31 0 : } 32 : 33 0 : ulong footprint = fd_rserve_footprint( ping_cache_entries ); 34 0 : if( FD_UNLIKELY( !footprint ) ) { 35 0 : FD_LOG_WARNING(( "bad ping cache size (%lu)", ping_cache_entries )); 36 0 : return NULL; 37 0 : } 38 : 39 0 : ulong ping_max = fd_ulong_pow2_up( ping_cache_entries ); 40 : 41 0 : FD_SCRATCH_ALLOC_INIT( l, shmem ); 42 0 : void * rserve_mem = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_rserve_t), sizeof(fd_rserve_t) ); 43 0 : void * ping_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, ping_pool_align(), ping_pool_footprint( ping_max ) ); 44 0 : void * ping_map_mem = FD_SCRATCH_ALLOC_APPEND( l, ping_map_align(), ping_map_footprint( ping_map_chain_cnt_est( ping_max ) ) ); 45 0 : void * ping_dlist_mem = FD_SCRATCH_ALLOC_APPEND( l, ping_dlist_align(), ping_dlist_footprint() ); 46 : 47 0 : fd_rserve_t * rserve = (fd_rserve_t *)rserve_mem; 48 0 : ping_pool_new( ping_pool_mem, ping_max ); 49 0 : rserve->ping_pool = fd_type_pun( ping_pool_mem ); 50 0 : rserve->ping_map = ping_map_join ( ping_map_new ( ping_map_mem, ping_map_chain_cnt_est( ping_max ), seed ) ); 51 0 : rserve->ping_dlist = ping_dlist_join( ping_dlist_new( ping_dlist_mem ) ); 52 : 53 : /* Initialize rotating tokens. */ 54 0 : rserve->seed = seed; 55 0 : rserve->token_idx = 0UL; 56 0 : rserve->last_rotate_ts = 0UL; 57 0 : fd_rserve_derive_token( rserve->token_cur, seed, 0UL ); 58 0 : fd_rserve_derive_token( rserve->token_prev, seed, 0UL ); 59 : 60 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_rserve_align() )==(ulong)shmem + footprint ); 61 : 62 0 : return shmem; 63 0 : } 64 : 65 : fd_rserve_t * 66 0 : fd_rserve_join( void * shrserve ) { 67 0 : if( FD_UNLIKELY( !shrserve ) ) { 68 0 : FD_LOG_WARNING(( "NULL rserve" )); 69 0 : return NULL; 70 0 : } 71 : 72 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shrserve, fd_rserve_align() ) ) ) { 73 0 : FD_LOG_WARNING(( "misaligned rserve" )); 74 0 : return NULL; 75 0 : } 76 : 77 0 : fd_rserve_t * rserve = (fd_rserve_t *)shrserve; 78 0 : rserve->ping_pool = ping_pool_join ( rserve->ping_pool ); 79 0 : rserve->ping_map = ping_map_join ( rserve->ping_map ); 80 0 : rserve->ping_dlist = ping_dlist_join( rserve->ping_dlist ); 81 : 82 0 : return (fd_rserve_t *)rserve; 83 0 : } 84 : 85 : void * 86 0 : fd_rserve_leave( fd_rserve_t const * rserve ) { 87 0 : if( FD_UNLIKELY( !rserve ) ) { 88 0 : FD_LOG_WARNING(( "NULL rserve" )); 89 0 : return NULL; 90 0 : } 91 : 92 0 : return (void *)rserve; 93 0 : } 94 : 95 : void * 96 0 : fd_rserve_delete( void * rserve ) { 97 0 : if( FD_UNLIKELY( !rserve ) ) { 98 0 : FD_LOG_WARNING(( "NULL rserve" )); 99 0 : return NULL; 100 0 : } 101 : 102 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)rserve, fd_rserve_align() ) ) ) { 103 0 : FD_LOG_WARNING(( "misaligned rserve" )); 104 0 : return NULL; 105 0 : } 106 : 107 0 : return rserve; 108 0 : } 109 : 110 : int 111 : fd_rserve_pong_token_verify( fd_rserve_t const * rserve, 112 0 : uchar const * pong_hash ) { 113 : /* The pong hash is SHA-256( "SOLANA_PING_PONG" || token ). 114 : Compute the expected hash for both current and previous tokens 115 : and check if either matches. */ 116 : 117 0 : uchar preimage[ FD_REPAIR_PONG_PREIMAGE_SZ ]; 118 0 : uchar expected[ 32 ]; 119 : 120 : /* Check current token. */ 121 0 : preimage_pong( (fd_hash_t const *)rserve->token_cur, preimage ); 122 0 : fd_sha256_hash( preimage, FD_REPAIR_PONG_PREIMAGE_SZ, expected ); 123 0 : if( FD_LIKELY( !memcmp( expected, pong_hash, 32UL ) ) ) return 1; 124 : 125 : /* Check previous token. */ 126 0 : preimage_pong( (fd_hash_t const *)rserve->token_prev, preimage ); 127 0 : fd_sha256_hash( preimage, FD_REPAIR_PONG_PREIMAGE_SZ, expected ); 128 0 : if( FD_LIKELY( !memcmp( expected, pong_hash, 32UL ) ) ) return 1; 129 : 130 0 : return 0; 131 0 : } 132 :