Line data Source code
1 : #include "fd_sysvar_cache.h"
2 : #include "fd_sysvar_cache_private.h"
3 : #include "fd_sysvar_recent_hashes.h"
4 : #include "fd_sysvar_slot_hashes.h"
5 : #include "fd_sysvar_slot_history.h"
6 : #include "fd_sysvar_stake_history.h"
7 :
8 : #include <errno.h>
9 :
10 : void *
11 8301 : fd_sysvar_cache_new( void * mem ) {
12 :
13 8301 : if( FD_UNLIKELY( !mem ) ) {
14 3 : FD_LOG_WARNING(( "NULL mem" ));
15 3 : return NULL;
16 3 : }
17 8298 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_sysvar_cache_t) ) ) ) {
18 3 : FD_LOG_WARNING(( "misaligned mem" ));
19 3 : return NULL;
20 3 : }
21 :
22 8295 : fd_sysvar_cache_t * sysvar_cache = mem;
23 8295 : sysvar_cache->magic = 0UL;
24 8295 : memset( sysvar_cache->desc, 0, FD_SYSVAR_CACHE_ENTRY_CNT*sizeof(fd_sysvar_desc_t) );
25 :
26 8295 : FD_COMPILER_MFENCE();
27 8295 : sysvar_cache->magic = FD_SYSVAR_CACHE_MAGIC;
28 8295 : FD_COMPILER_MFENCE();
29 :
30 8295 : return sysvar_cache;
31 8298 : }
32 :
33 : fd_sysvar_cache_t *
34 8307 : fd_sysvar_cache_join( void * mem ) {
35 : /* FIXME This is a good place to ref-count writable joins */
36 8307 : return (fd_sysvar_cache_t *)fd_sysvar_cache_join_const( mem );
37 8307 : }
38 :
39 : fd_sysvar_cache_t const *
40 8316 : fd_sysvar_cache_join_const( void const * mem ) {
41 :
42 8316 : if( FD_UNLIKELY( !mem ) ) {
43 6 : FD_LOG_WARNING(( "NULL mem" ));
44 6 : return NULL;
45 6 : }
46 8310 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_sysvar_cache_t) ) ) ) {
47 6 : FD_LOG_WARNING(( "misaligned mem" ));
48 6 : return NULL;
49 6 : }
50 8304 : fd_sysvar_cache_t const * sysvar_cache = mem;
51 8304 : if( FD_UNLIKELY( sysvar_cache->magic != FD_SYSVAR_CACHE_MAGIC ) ) {
52 6 : FD_LOG_WARNING(( "bad magic" ));
53 6 : return NULL;
54 6 : }
55 :
56 8298 : return sysvar_cache;
57 8304 : }
58 :
59 : void *
60 8295 : fd_sysvar_cache_leave( fd_sysvar_cache_t * sysvar_cache ) {
61 8295 : return sysvar_cache;
62 8295 : }
63 :
64 : void const *
65 3 : fd_sysvar_cache_leave_const( fd_sysvar_cache_t const * sysvar_cache ) {
66 3 : return sysvar_cache;
67 3 : }
68 :
69 : void *
70 69 : fd_sysvar_cache_delete( void * mem ) {
71 :
72 69 : if( FD_UNLIKELY( !mem ) ) {
73 3 : FD_LOG_WARNING(( "NULL mem" ));
74 3 : return NULL;
75 3 : }
76 66 : fd_sysvar_cache_t * sysvar_cache = mem;
77 66 : if( FD_UNLIKELY( sysvar_cache->magic != FD_SYSVAR_CACHE_MAGIC ) ) {
78 3 : FD_LOG_WARNING(( "bad magic" ));
79 3 : return NULL;
80 3 : }
81 :
82 63 : memset( sysvar_cache, 0, sizeof(fd_sysvar_cache_t) );
83 :
84 63 : return mem;
85 66 : }
86 :
87 : uchar const *
88 : fd_sysvar_cache_data_query(
89 : fd_sysvar_cache_t const * sysvar_cache,
90 : void const * address, /* 32 bytes */
91 : ulong * psz
92 522 : ) {
93 522 : *psz = 0UL;
94 522 : fd_pubkey_t const pubkey = FD_LOAD( fd_pubkey_t, address );
95 522 : sysvar_tbl_t const * entry = sysvar_map_query( &pubkey, NULL );
96 522 : if( FD_UNLIKELY( !entry ) ) return NULL; /* address is not a sysvar */
97 519 : fd_sysvar_desc_t const * desc = &sysvar_cache->desc[ entry->desc_idx ];
98 519 : fd_sysvar_pos_t const * pos = &fd_sysvar_pos_tbl [ entry->desc_idx ];
99 519 : if( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) return NULL; /* sysvar data invalid */
100 492 : *psz = desc->data_sz;
101 492 : return (uchar const *)sysvar_cache + pos->data_off;
102 519 : }
103 :
104 : /* Generate accessors for sysvars that are backed by POD structs. */
105 :
106 : #define SIMPLE_SYSVAR_READ( name, name2, typet ) \
107 : typet * \
108 : fd_sysvar_cache_##name##_read( fd_sysvar_cache_t const * cache, \
109 36 : typet * out ) { \
110 36 : ulong const idx = FD_SYSVAR_##name##_IDX; \
111 36 : fd_sysvar_desc_t const * desc = &cache->desc[ idx ]; \
112 36 : fd_sysvar_pos_t const * pos = &fd_sysvar_pos_tbl[ idx ]; \
113 36 : if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL; \
114 36 : if( !pos->obj_max ) memcpy( out, (uchar *)cache+pos->data_off, pos->data_max ); \
115 18 : else memcpy( out, (uchar *)cache+pos->obj_off, pos->obj_max ); \
116 18 : return out; \
117 36 : }
118 :
119 : #define SIMPLE_SYSVAR( name, name2, type ) \
120 : SIMPLE_SYSVAR_READ( name, name2, fd_##type##_t )
121 18 : FD_SYSVAR_SIMPLE_ITER( SIMPLE_SYSVAR )
122 18 : #undef SIMPLE_SYSVAR
123 18 : #undef SIMPLE_SYSVAR_READ
124 18 :
125 18 : ulong const *
126 18 : fd_sysvar_cache_last_restart_slot_read( fd_sysvar_cache_t const * cache ) {
127 3 : ulong const idx = FD_SYSVAR_last_restart_slot_IDX;
128 3 : fd_sysvar_desc_t const * desc = &cache->desc[ idx ];
129 3 : fd_sysvar_pos_t const * pos = &fd_sysvar_pos_tbl[ idx ];
130 3 : if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL;
131 0 : return fd_type_pun_const( (uchar const *)cache + pos->data_off );
132 3 : }
133 :
134 : int
135 9 : fd_sysvar_cache_recent_hashes_is_empty( fd_sysvar_cache_t const * sysvar_cache ) {
136 9 : fd_sysvar_desc_t const * desc = &sysvar_cache->desc[ FD_SYSVAR_recent_hashes_IDX ];
137 9 : if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return 1;
138 9 : FD_TEST( desc->data_sz >= sizeof(ulong) );
139 9 : ulong len = FD_LOAD( ulong, sysvar_cache->bin_recent_hashes );
140 9 : return len == 0UL;
141 9 : }
142 :
143 : int
144 : fd_sysvar_obj_restore( fd_sysvar_cache_t * cache,
145 : fd_sysvar_desc_t * desc,
146 62040 : fd_sysvar_pos_t const * pos ) {
147 62040 : desc->flags &= ~FD_SYSVAR_FLAG_VALID;
148 :
149 62040 : uchar const * data = (uchar const *)cache + pos->data_off;
150 62040 : ulong const data_sz = desc->data_sz;
151 :
152 62040 : if( FD_UNLIKELY( !pos->validate( data, data_sz ) ) ) {
153 9 : FD_LOG_DEBUG(( "Failed to validate sysvar %s with data_sz=%lu",
154 9 : pos->name, data_sz ));
155 9 : return EINVAL;
156 9 : }
157 62031 : desc->flags |= FD_SYSVAR_FLAG_VALID;
158 62031 : return 0;
159 62040 : }
160 :
161 : #define TYPES_CALLBACKS( name, suf ) \
162 : .decode_footprint = fd_##name##_decode_footprint, \
163 : .decode = (__typeof__(((fd_sysvar_pos_t *)NULL)->decode))(ulong)fd_##name##_decode##suf
164 :
165 : static int
166 7743 : fd_sysvar_validate_clock( uchar const * data, ulong data_sz ) {
167 7743 : (void)data;
168 7743 : return data_sz >= sizeof(fd_sol_sysvar_clock_t );
169 7743 : }
170 :
171 : static int
172 7737 : fd_sysvar_validate_rent( uchar const * data, ulong data_sz ) {
173 7737 : (void)data;
174 7737 : return data_sz >= sizeof(fd_rent_t );
175 7737 : }
176 :
177 : static int
178 7737 : fd_sysvar_validate_last_restart_slot( uchar const * data, ulong data_sz ) {
179 7737 : (void)data;
180 7737 : return data_sz >= sizeof(ulong);
181 7737 : }
182 :
183 : static int
184 618 : fd_sysvar_validate_epoch_rewards( uchar const * data, ulong data_sz ) {
185 618 : if( FD_UNLIKELY( data_sz < sizeof(fd_sysvar_epoch_rewards_t) ) ) return 0;
186 618 : fd_sysvar_epoch_rewards_t ew = FD_LOAD( fd_sysvar_epoch_rewards_t, data );
187 618 : uchar active = ew.active;
188 618 : if( FD_UNLIKELY( active!=0 && active!=1 ) ) return 0;
189 615 : return 1;
190 618 : }
191 :
192 : static int
193 7740 : fd_sysvar_validate_epoch_schedule( uchar const * data, ulong data_sz ) {
194 7740 : if( FD_UNLIKELY( data_sz < sizeof(fd_epoch_schedule_t) ) ) return 0;
195 7740 : fd_epoch_schedule_t es = FD_LOAD( fd_epoch_schedule_t, data );
196 7740 : uchar warmup = es.warmup;
197 7740 : if( FD_UNLIKELY( warmup!=0 && warmup!=1 ) ) return 0;
198 7737 : return 1;
199 7740 : }
200 :
201 : fd_sysvar_pos_t const fd_sysvar_pos_tbl[ FD_SYSVAR_CACHE_ENTRY_CNT ] = {
202 : [FD_SYSVAR_clock_IDX] =
203 : { .name="clock",
204 : .data_off=offsetof(fd_sysvar_cache_t, bin_clock ), .data_max=FD_SYSVAR_CLOCK_BINCODE_SZ,
205 : .validate=fd_sysvar_validate_clock },
206 : [FD_SYSVAR_epoch_rewards_IDX] =
207 : { .name="epoch rewards",
208 : .data_off=offsetof(fd_sysvar_cache_t, bin_epoch_rewards ), .data_max=FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ,
209 : .validate=fd_sysvar_validate_epoch_rewards },
210 : [FD_SYSVAR_epoch_schedule_IDX] =
211 : { .name="epoch schedule",
212 : .data_off=offsetof(fd_sysvar_cache_t, bin_epoch_schedule ), .data_max=FD_SYSVAR_EPOCH_SCHEDULE_BINCODE_SZ,
213 : .validate=fd_sysvar_validate_epoch_schedule },
214 : [FD_SYSVAR_last_restart_slot_IDX] =
215 : { .name="last restart slot",
216 : .data_off=offsetof(fd_sysvar_cache_t, bin_last_restart_slot), .data_max=FD_SYSVAR_LAST_RESTART_SLOT_BINCODE_SZ,
217 : .validate=fd_sysvar_validate_last_restart_slot },
218 : [FD_SYSVAR_recent_hashes_IDX] =
219 : { .name="recent blockhashes",
220 : .data_off=offsetof(fd_sysvar_cache_t, bin_recent_hashes ), .data_max=FD_SYSVAR_RECENT_HASHES_BINCODE_SZ,
221 : .validate=fd_sysvar_recent_hashes_validate },
222 : [FD_SYSVAR_rent_IDX] =
223 : { .name="rent",
224 : .data_off=offsetof(fd_sysvar_cache_t, bin_rent ), .data_max=FD_SYSVAR_RENT_BINCODE_SZ,
225 : .validate=fd_sysvar_validate_rent },
226 : [FD_SYSVAR_slot_hashes_IDX] =
227 : { .name="slot hashes",
228 : .data_off=offsetof(fd_sysvar_cache_t, bin_slot_hashes ), .data_max=FD_SYSVAR_SLOT_HASHES_BINCODE_SZ,
229 : .validate=fd_sysvar_slot_hashes_validate },
230 : [FD_SYSVAR_slot_history_IDX] =
231 : { .name="slot history",
232 : .data_off=offsetof(fd_sysvar_cache_t, bin_slot_history ), .data_max=FD_SYSVAR_SLOT_HISTORY_BINCODE_SZ,
233 : .validate=fd_sysvar_slot_history_validate },
234 : [FD_SYSVAR_stake_history_IDX] =
235 : { .name="stake history",
236 : .data_off=offsetof(fd_sysvar_cache_t, bin_stake_history ), .data_max=FD_SYSVAR_STAKE_HISTORY_BINCODE_SZ,
237 : .validate=fd_sysvar_stake_history_validate },
238 : };
239 :
240 : fd_slot_hashes_t *
241 : fd_sysvar_cache_slot_hashes_view( fd_sysvar_cache_t const * cache,
242 132 : fd_slot_hashes_t * view ) {
243 132 : fd_sysvar_desc_t const * desc = &cache->desc[ FD_SYSVAR_slot_hashes_IDX ];
244 132 : if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL;
245 132 : return fd_sysvar_slot_hashes_view( view, cache->bin_slot_hashes, desc->data_sz );
246 132 : }
247 :
248 : fd_stake_history_t *
249 : fd_sysvar_cache_stake_history_view( fd_sysvar_cache_t const * cache,
250 996 : fd_stake_history_t * view ) {
251 996 : fd_sysvar_desc_t const * desc = &cache->desc[ FD_SYSVAR_stake_history_IDX ];
252 996 : if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL;
253 900 : return fd_sysvar_stake_history_view( view, cache->bin_stake_history, desc->data_sz );
254 996 : }
255 :
256 : #undef TYPES_CALLBACKS
|