Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_tests_fd_svm_mini_h
2 : #define HEADER_fd_src_flamenco_runtime_tests_fd_svm_mini_h
3 :
4 : /* fd_svm_mini.h is an API for creating Solana runtime test
5 : environments.
6 :
7 : Structurally, the API works as follows:
8 : - svm_mini provides an environment for block/transaction execution,
9 : including a fork-aware accounts DB, program cache, etc.
10 : - svm_mini_limits configures memory limits for the above
11 : - svm_mini_params fine-tunes default state to reduce setup
12 : boilerplate (e.g. set up vote/stake accounts, builtin programs)
13 : - forks are identified by the "bank index". some care is required to
14 : handle bank indexes, as they are reused after invalidation.
15 :
16 : This API optimizes for testing, not useful for production:
17 : - smaller runtime defaults (aims for 2 GiB memory reservations)
18 : - memory lazy paged / not pinned by default
19 : - memory 4K paged by default (simplify startup)
20 : - avoids use of privileged kernel calls */
21 :
22 : #include "../../progcache/fd_progcache_user.h"
23 : #include "../../log_collector/fd_log_collector_base.h"
24 : #include "../fd_runtime.h"
25 : #include "../fd_runtime_stack.h"
26 : #include "../fd_txncache.h"
27 : #include "../../vm/fd_vm.h"
28 :
29 : /* fd_svm_mini_t holds handles to all relevant Firedancer runtime
30 : components for test environments. */
31 :
32 : struct fd_svm_mini {
33 : fd_wksp_t * wksp;
34 : fd_banks_t * banks;
35 : fd_runtime_t * runtime;
36 : fd_runtime_stack_t * runtime_stack;
37 : fd_txncache_shmem_t * txncache_shmem;
38 : fd_txncache_t * txncache;
39 : fd_vm_t * vm;
40 :
41 : fd_progcache_t progcache[1];
42 : fd_log_collector_t log_collector[1];
43 : fd_features_t features[1];
44 : fd_sha256_t sha256[1]; /* FIXME this should not be separate */
45 :
46 : /* Saved accdb init params for reset */
47 : int accdb_fd;
48 : void * accdb_shmem_mem;
49 : void * accdb_join_mem;
50 : ulong accdb_max_accounts;
51 : ulong accdb_max_live_slots;
52 : ulong accdb_joiner_cnt;
53 : };
54 :
55 : typedef struct fd_svm_mini fd_svm_mini_t;
56 :
57 : /* fd_svm_mini_limits_t specifies memory allocation limits for runtime
58 : components. */
59 :
60 : struct fd_svm_mini_limits {
61 : /* fork management */
62 : ulong max_live_slots;
63 : ulong max_fork_width;
64 :
65 : /* consensus */
66 : ulong max_vote_accounts;
67 : ulong max_stake_accounts;
68 : ulong max_fallback_stake_accounts;
69 :
70 : /* accdb */
71 : ulong max_accounts;
72 : ulong max_account_space_bytes;
73 :
74 : /* Number of accdb joiners (writer joins) the shmem must support. 0
75 : means 1 (just the mini's own runtime join). Tests that join the
76 : accdb a second time (e.g. an exec tile sharing mini's accounts DB)
77 : must set this to at least 2. */
78 : ulong accdb_joiner_cnt;
79 :
80 : /* progcache */
81 : ulong max_progcache_recs;
82 : ulong max_progcache_heap_bytes;
83 :
84 : /* txn executor */
85 : ulong max_txn_write_locks;
86 : ulong max_txn_per_slot;
87 :
88 : /* wksp alloc tag (0 uses default) */
89 : ulong wksp_tag;
90 :
91 : /* additional wksp partitions / data size */
92 : ulong wksp_addl_part_cnt;
93 : ulong wksp_addl_sz;
94 : };
95 :
96 : typedef struct fd_svm_mini_limits fd_svm_mini_limits_t;
97 :
98 : /* fd_svm_mini_params_t specifies defaults for initialization of an
99 : svm_mini object. */
100 :
101 : struct fd_svm_mini_params {
102 : ulong hash_seed;
103 : ulong root_slot;
104 : ulong slots_per_epoch;
105 :
106 : ulong init_sysvars : 1;
107 : ulong init_feature_accounts : 1;
108 : ulong init_builtins : 1;
109 :
110 : /* If non-zero, creates mock_validator_cnt validators with uniform
111 : stake and populates the epoch leader schedule. For each validator,
112 : creates identity, vote, and stake accounts in the accounts DB. */
113 : ulong mock_validator_cnt;
114 :
115 : /* Sysvar overrides */
116 : fd_sol_sysvar_clock_t const * clock;
117 : fd_epoch_schedule_t const * epoch_schedule;
118 : fd_rent_t const * rent;
119 : };
120 :
121 : typedef struct fd_svm_mini_params fd_svm_mini_params_t;
122 :
123 : FD_PROTOTYPES_BEGIN
124 :
125 : /* fd_svm_test_{boot,halt} do all-in-one setup for test executables.
126 : An important goal is rootless operation on a default Linux config for
127 : easy development.
128 :
129 : fd_svm_test_boot does the following steps:
130 : - standard command-line handling
131 : - creates an anonymous wksp / attaches to an existing wksp
132 : - creates various runtime objects
133 :
134 : Parses and strips the following arguments from pargc/pargv, or
135 : chooses sane defaults in the absence of these options.
136 :
137 : --page-sz <size> memory page size ("normal", "huge", "gigantic")
138 : if unspecified, uses lazy anonymous normal pages
139 : if specified, implies pinned/mlock() pages
140 : --page-cnt <count> number of memory pages to reserve (default derived from limits)
141 : --wksp <name> use existing wksp instead of allocating one
142 : --near-cpu <number> NUMA affinity hint for memory allocations
143 : (default: let kernel decide on first use/mlock)
144 :
145 : Terminates the process with FD_LOG_ERR (exit code 1) if svm_mini
146 : fails to boot.
147 :
148 : fd_svm_test_halt destroys the mini object and halts fd. Wksp
149 : cleanup is left to process termination. */
150 :
151 : fd_svm_mini_t *
152 : fd_svm_test_boot( int * pargc,
153 : char *** pargv,
154 : fd_svm_mini_limits_t const * limits );
155 :
156 : void
157 : fd_svm_test_halt( fd_svm_mini_t * mini );
158 :
159 : /* fd_svm_mini_limits_default populates minimal single-fork execution
160 : limits. */
161 :
162 : FD_FN_UNUSED static fd_svm_mini_limits_t *
163 57 : fd_svm_mini_limits_default( fd_svm_mini_limits_t * limits ) {
164 57 : *limits = (fd_svm_mini_limits_t) {
165 57 : .max_live_slots = 16UL,
166 57 : .max_fork_width = 4UL,
167 57 : .max_vote_accounts = 256UL,
168 57 : .max_stake_accounts = 256UL,
169 57 : .max_fallback_stake_accounts = 4096UL,
170 57 : .max_accounts = 128UL,
171 57 : .max_account_space_bytes = 32UL<<20,
172 57 : .max_progcache_recs = 256UL,
173 57 : .max_progcache_heap_bytes = 65536UL,
174 57 : .max_txn_write_locks = 0UL,
175 57 : .max_txn_per_slot = 128UL
176 57 : };
177 57 : return limits;
178 57 : }
179 :
180 : /* fd_svm_mini_wksp_data_max returns the recommended heap space in bytes
181 : for a given limits config. */
182 :
183 : ulong
184 : fd_svm_mini_wksp_data_max( fd_svm_mini_limits_t const * limits );
185 :
186 : /* fd_svm_mini_create allocates and constructs various Solana runtime
187 : environment objects and packs them into an svm_mini handle. The
188 : newly created svm_mini object is reset using default params. On
189 : failure terminates the app with FD_LOG_ERR (exit code 1). */
190 :
191 : fd_svm_mini_t *
192 : fd_svm_mini_create( fd_wksp_t * wksp,
193 : fd_svm_mini_limits_t const * limits );
194 :
195 : /* fd_svm_mini_destroy destroys all Solana runtime environment objects,
196 : accounts, blocks, etc, and frees them back to the wksp heap. */
197 :
198 : void
199 : fd_svm_mini_destroy( fd_svm_mini_t * mini );
200 :
201 : /* fd_svm_mini_params_default populates default execution state. */
202 :
203 : FD_FN_UNUSED static fd_svm_mini_params_t *
204 3909 : fd_svm_mini_params_default( fd_svm_mini_params_t * params ) {
205 3909 : *params = (fd_svm_mini_params_t) {
206 3909 : .hash_seed = 1UL,
207 3909 : .root_slot = 1UL,
208 3909 : .slots_per_epoch = 16UL,
209 3909 : .init_sysvars = 1,
210 3909 : .init_feature_accounts = 0,
211 3909 : .init_builtins = 1,
212 3909 : .mock_validator_cnt = 1UL,
213 3909 : .clock = NULL,
214 3909 : .epoch_schedule = NULL,
215 : .rent = NULL,
216 3909 : };
217 3909 : return params;
218 3909 : }
219 :
220 : /* fd_svm_mini_reset destroys all existing runtime state (banks, accdb,
221 : etc), and initializes them according to params. This operation
222 : invalidates any handle previously acquired through svm_mini. Returns
223 : the initial bank index (rooted), or ULONG_MAX if mock_validator_cnt
224 : exceeds the configured vote-account capacity. */
225 :
226 : ulong
227 : fd_svm_mini_reset( fd_svm_mini_t * mini,
228 : fd_svm_mini_params_t * params );
229 :
230 : /* Fork management API */
231 :
232 : /* fd_svm_mini_attach_child creates a fork node as a descendant of the
233 : node identified by parent_bank_idx. child_slot is the slot number of
234 : this node. Terminates the app with FD_LOG_ERR on failure. */
235 :
236 : ulong
237 : fd_svm_mini_attach_child( fd_svm_mini_t * mini,
238 : ulong parent_bank_idx,
239 : ulong child_slot );
240 :
241 : /* fd_svm_mini_freeze freezes the bank identified by bank_idx. Runs
242 : slot boundary logic (registers POH hash into blockhash queue, updates
243 : sysvars, settles fees, etc). */
244 :
245 : void
246 : fd_svm_mini_freeze( fd_svm_mini_t * mini,
247 : ulong bank_idx );
248 :
249 : /* fd_svm_mini_register_blockhash makes blockhash resolvable by the
250 : status cache when executing transactions on the bank identified by
251 : bank_idx (otherwise the fd_txncache_query/insert FD_TEST(blockcache)
252 : in the executor's pre-execute checks fails). It registers blockhash
253 : on bank_idx's PARENT txncache fork, because a fork can only query
254 : blockhashes registered on a fork it descends from (a fork's
255 : descends-set holds its ancestors, not itself). bank_idx must
256 : therefore have a parent, and that parent fork must not already be
257 : finalized (each txncache fork carries at most one blockhash). */
258 :
259 : void
260 : fd_svm_mini_register_blockhash( fd_svm_mini_t * mini,
261 : ulong bank_idx,
262 : fd_hash_t const * blockhash );
263 :
264 : /* fd_svm_mini_cancel_fork cancels the subtree of the fork graph
265 : identified by bank_idx (i.e. the bank_idx node and all its children,
266 : transitively). */
267 :
268 : void
269 : fd_svm_mini_cancel_fork( fd_svm_mini_t * mini,
270 : ulong bank_idx );
271 :
272 : /* fd_svm_mini_advance_root advances the fork graph root to the node
273 : identified by bank_idx. Cancels all siblings and uncles
274 : (transitively) of the rooted nodes. */
275 :
276 : void
277 : fd_svm_mini_advance_root( fd_svm_mini_t * mini,
278 : ulong bank_idx );
279 :
280 : fd_bank_t *
281 : fd_svm_mini_bank( fd_svm_mini_t * mini,
282 : ulong bank_idx );
283 :
284 : fd_accdb_fork_id_t
285 : fd_svm_mini_fork_id( fd_svm_mini_t * mini,
286 : ulong bank_idx );
287 :
288 : /* Mock/inject API */
289 :
290 : /* fd_svm_mini_put_account_rooted injects a copy of the account at ro
291 : into the rooted state. */
292 :
293 : void
294 : fd_svm_mini_put_account_rooted( fd_svm_mini_t * mini,
295 : fd_acc_t const * ro );
296 :
297 : /* fd_svm_mini_add_lamports_rooted increases the lamport balance of a
298 : rooted accounts. */
299 :
300 : void
301 : fd_svm_mini_add_lamports_rooted( fd_svm_mini_t * mini,
302 : fd_pubkey_t const * pubkey,
303 : ulong lamports );
304 :
305 : /* fd_svm_mini_add_lamports increases the lamport balance of an account. */
306 :
307 : void
308 : fd_svm_mini_add_lamports( fd_svm_mini_t * mini,
309 : fd_accdb_fork_id_t fork_id,
310 : fd_pubkey_t const * pubkey,
311 : ulong lamports );
312 :
313 : FD_PROTOTYPES_END
314 :
315 : #endif /* HEADER_fd_src_flamenco_runtime_tests_fd_svm_mini_h */
|