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 7947 : fd_sysvar_cache_new( void * mem ) {
12 :
13 7947 : if( FD_UNLIKELY( !mem ) ) {
14 3 : FD_LOG_WARNING(( "NULL mem" ));
15 3 : return NULL;
16 3 : }
17 7944 : 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 7941 : fd_sysvar_cache_t * sysvar_cache = mem;
23 7941 : sysvar_cache->magic = 0UL;
24 7941 : memset( sysvar_cache->desc, 0, FD_SYSVAR_CACHE_ENTRY_CNT*sizeof(fd_sysvar_desc_t) );
25 :
26 7941 : FD_COMPILER_MFENCE();
27 7941 : sysvar_cache->magic = FD_SYSVAR_CACHE_MAGIC;
28 7941 : FD_COMPILER_MFENCE();
29 :
30 7941 : return sysvar_cache;
31 7944 : }
32 :
33 : fd_sysvar_cache_t *
34 7953 : fd_sysvar_cache_join( void * mem ) {
35 : /* FIXME This is a good place to ref-count writable joins */
36 7953 : return (fd_sysvar_cache_t *)fd_sysvar_cache_join_const( mem );
37 7953 : }
38 :
39 : fd_sysvar_cache_t const *
40 7962 : fd_sysvar_cache_join_const( void const * mem ) {
41 :
42 7962 : if( FD_UNLIKELY( !mem ) ) {
43 6 : FD_LOG_WARNING(( "NULL mem" ));
44 6 : return NULL;
45 6 : }
46 7956 : 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 7950 : fd_sysvar_cache_t const * sysvar_cache = mem;
51 7950 : 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 7944 : return sysvar_cache;
57 7950 : }
58 :
59 : void *
60 7941 : fd_sysvar_cache_leave( fd_sysvar_cache_t * sysvar_cache ) {
61 7941 : return sysvar_cache;
62 7941 : }
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 45 : typet * out ) { \
110 45 : ulong const idx = FD_SYSVAR_##name##_IDX; \
111 45 : fd_sysvar_desc_t const * desc = &cache->desc[ idx ]; \
112 45 : fd_sysvar_pos_t const * pos = &fd_sysvar_pos_tbl[ idx ]; \
113 45 : if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL; \
114 45 : if( !pos->obj_max ) memcpy( out, (uchar *)cache+pos->data_off, pos->data_max ); \
115 27 : else memcpy( out, (uchar *)cache+pos->obj_off, pos->obj_max ); \
116 27 : return out; \
117 45 : }
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 59613 : fd_sysvar_pos_t const * pos ) {
147 59613 : desc->flags &= ~FD_SYSVAR_FLAG_VALID;
148 :
149 59613 : uchar const * data = (uchar const *)cache + pos->data_off;
150 59613 : ulong const data_sz = desc->data_sz;
151 :
152 59613 : 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 59604 : desc->flags |= FD_SYSVAR_FLAG_VALID;
158 59604 : return 0;
159 59613 : }
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 7389 : fd_sysvar_validate_clock( uchar const * data, ulong data_sz ) {
167 7389 : (void)data;
168 7389 : return data_sz >= sizeof(fd_sol_sysvar_clock_t );
169 7389 : }
170 :
171 : static int
172 7383 : fd_sysvar_validate_rent( uchar const * data, ulong data_sz ) {
173 7383 : (void)data;
174 7383 : return data_sz >= sizeof(fd_rent_t );
175 7383 : }
176 :
177 : static int
178 7383 : fd_sysvar_validate_last_restart_slot( uchar const * data, ulong data_sz ) {
179 7383 : (void)data;
180 7383 : return data_sz >= sizeof(ulong);
181 7383 : }
182 :
183 : static int
184 315 : fd_sysvar_validate_epoch_rewards( uchar const * data, ulong data_sz ) {
185 315 : if( FD_UNLIKELY( data_sz < sizeof(fd_sysvar_epoch_rewards_t) ) ) return 0;
186 315 : fd_sysvar_epoch_rewards_t ew = FD_LOAD( fd_sysvar_epoch_rewards_t, data );
187 315 : uchar active = ew.active;
188 315 : if( FD_UNLIKELY( active!=0 && active!=1 ) ) return 0;
189 312 : return 1;
190 315 : }
191 :
192 : static int
193 7386 : fd_sysvar_validate_epoch_schedule( uchar const * data, ulong data_sz ) {
194 7386 : if( FD_UNLIKELY( data_sz < sizeof(fd_epoch_schedule_t) ) ) return 0;
195 7386 : fd_epoch_schedule_t es = FD_LOAD( fd_epoch_schedule_t, data );
196 7386 : uchar warmup = es.warmup;
197 7386 : if( FD_UNLIKELY( warmup!=0 && warmup!=1 ) ) return 0;
198 7383 : return 1;
199 7386 : }
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 660 : fd_stake_history_t * view ) {
251 660 : fd_sysvar_desc_t const * desc = &cache->desc[ FD_SYSVAR_stake_history_IDX ];
252 660 : if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL;
253 564 : return fd_sysvar_stake_history_view( view, cache->bin_stake_history, desc->data_sz );
254 660 : }
255 :
256 : #undef TYPES_CALLBACKS
|