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 :
69 : /* accdb */
70 : ulong max_accounts;
71 : ulong max_account_space_bytes;
72 :
73 : /* Number of accdb joiners (writer joins) the shmem must support. 0
74 : means 1 (just the mini's own runtime join). Tests that join the
75 : accdb a second time (e.g. an exec tile sharing mini's accounts DB)
76 : must set this to at least 2. */
77 : ulong accdb_joiner_cnt;
78 :
79 : /* progcache */
80 : ulong max_progcache_recs;
81 : ulong max_progcache_heap_bytes;
82 :
83 : /* txn executor */
84 : ulong max_txn_write_locks;
85 : ulong max_txn_per_slot;
86 :
87 : /* wksp alloc tag (0 uses default) */
88 : ulong wksp_tag;
89 :
90 : /* additional wksp partitions / data size */
91 : ulong wksp_addl_part_cnt;
92 : ulong wksp_addl_sz;
93 : };
94 :
95 : typedef struct fd_svm_mini_limits fd_svm_mini_limits_t;
96 :
97 : /* fd_svm_mini_params_t specifies defaults for initialization of an
98 : svm_mini object. */
99 :
100 : struct fd_svm_mini_params {
101 : ulong hash_seed;
102 : ulong root_slot;
103 : ulong slots_per_epoch;
104 :
105 : ulong init_sysvars : 1;
106 : ulong init_feature_accounts : 1;
107 : ulong init_builtins : 1;
108 :
109 : /* If non-zero, creates mock_validator_cnt validators with uniform
110 : stake and populates the epoch leader schedule. For each validator,
111 : creates identity, vote, and stake accounts in the accounts DB. */
112 : ulong mock_validator_cnt;
113 :
114 : /* Sysvar overrides */
115 : fd_sol_sysvar_clock_t const * clock;
116 : fd_epoch_schedule_t const * epoch_schedule;
117 : fd_rent_t const * rent;
118 : };
119 :
120 : typedef struct fd_svm_mini_params fd_svm_mini_params_t;
121 :
122 : FD_PROTOTYPES_BEGIN
123 :
124 : /* fd_svm_test_{boot,halt} do all-in-one setup for test executables.
125 : An important goal is rootless operation on a default Linux config for
126 : easy development.
127 :
128 : fd_svm_test_boot does the following steps:
129 : - standard command-line handling
130 : - creates an anonymous wksp / attaches to an existing wksp
131 : - creates various runtime objects
132 :
133 : Parses and strips the following arguments from pargc/pargv, or
134 : chooses sane defaults in the absence of these options.
135 :
136 : --page-sz <size> memory page size ("normal", "huge", "gigantic")
137 : if unspecified, uses lazy anonymous normal pages
138 : if specified, implies pinned/mlock() pages
139 : --page-cnt <count> number of memory pages to reserve (default derived from limits)
140 : --wksp <name> use existing wksp instead of allocating one
141 : --near-cpu <number> NUMA affinity hint for memory allocations
142 : (default: let kernel decide on first use/mlock)
143 :
144 : Terminates the process with FD_LOG_ERR (exit code 1) if svm_mini
145 : fails to boot.
146 :
147 : fd_svm_test_halt destroys the mini object and halts fd. Wksp
148 : cleanup is left to process termination. */
149 :
150 : fd_svm_mini_t *
151 : fd_svm_test_boot( int * pargc,
152 : char *** pargv,
153 : fd_svm_mini_limits_t const * limits );
154 :
155 : void
156 : fd_svm_test_halt( fd_svm_mini_t * mini );
157 :
158 : /* fd_svm_mini_limits_default populates minimal single-fork execution
159 : limits. */
160 :
161 : FD_FN_UNUSED static fd_svm_mini_limits_t *
162 57 : fd_svm_mini_limits_default( fd_svm_mini_limits_t * limits ) {
163 57 : *limits = (fd_svm_mini_limits_t) {
164 57 : .max_live_slots = 16UL,
165 57 : .max_fork_width = 4UL,
166 57 : .max_vote_accounts = 256UL,
167 57 : .max_stake_accounts = 256UL,
168 57 : .max_accounts = 128UL,
169 57 : .max_account_space_bytes = 32UL<<20,
170 57 : .max_progcache_recs = 256UL,
171 57 : .max_progcache_heap_bytes = 65536UL,
172 57 : .max_txn_write_locks = 0UL,
173 57 : .max_txn_per_slot = 128UL
174 57 : };
175 57 : return limits;
176 57 : }
177 :
178 : /* fd_svm_mini_wksp_data_max returns the recommended heap space in bytes
179 : for a given limits config. */
180 :
181 : ulong
182 : fd_svm_mini_wksp_data_max( fd_svm_mini_limits_t const * limits );
183 :
184 : /* fd_svm_mini_create allocates and constructs various Solana runtime
185 : environment objects and packs them into an svm_mini handle. The
186 : newly created svm_mini object is reset using default params. On
187 : failure terminates the app with FD_LOG_ERR (exit code 1). */
188 :
189 : fd_svm_mini_t *
190 : fd_svm_mini_create( fd_wksp_t * wksp,
191 : fd_svm_mini_limits_t const * limits );
192 :
193 : /* fd_svm_mini_destroy destroys all Solana runtime environment objects,
194 : accounts, blocks, etc, and frees them back to the wksp heap. */
195 :
196 : void
197 : fd_svm_mini_destroy( fd_svm_mini_t * mini );
198 :
199 : /* fd_svm_mini_params_default populates default execution state. */
200 :
201 : FD_FN_UNUSED static fd_svm_mini_params_t *
202 3651 : fd_svm_mini_params_default( fd_svm_mini_params_t * params ) {
203 3651 : *params = (fd_svm_mini_params_t) {
204 3651 : .hash_seed = 1UL,
205 3651 : .root_slot = 1UL,
206 3651 : .slots_per_epoch = 16UL,
207 3651 : .init_sysvars = 1,
208 3651 : .init_feature_accounts = 0,
209 3651 : .init_builtins = 1,
210 3651 : .mock_validator_cnt = 1UL,
211 3651 : .clock = NULL,
212 3651 : .epoch_schedule = NULL,
213 : .rent = NULL,
214 3651 : };
215 3651 : return params;
216 3651 : }
217 :
218 : /* fd_svm_mini_reset destroys all existing runtime state (banks, accdb,
219 : etc), and initializes them according to params. This operation
220 : invalidates any handle previously acquired through svm_mini. Returns
221 : the initial bank index (rooted). */
222 :
223 : ulong
224 : fd_svm_mini_reset( fd_svm_mini_t * mini,
225 : fd_svm_mini_params_t * params );
226 :
227 : /* Fork management API */
228 :
229 : /* fd_svm_mini_attach_child creates a fork node as a descendant of the
230 : node identified by parent_bank_idx. child_slot is the slot number of
231 : this node. Terminates the app with FD_LOG_ERR on failure. */
232 :
233 : ulong
234 : fd_svm_mini_attach_child( fd_svm_mini_t * mini,
235 : ulong parent_bank_idx,
236 : ulong child_slot );
237 :
238 : /* fd_svm_mini_freeze freezes the bank identified by bank_idx. Runs
239 : slot boundary logic (registers POH hash into blockhash queue, updates
240 : sysvars, settles fees, etc). */
241 :
242 : void
243 : fd_svm_mini_freeze( fd_svm_mini_t * mini,
244 : ulong bank_idx );
245 :
246 : /* fd_svm_mini_register_blockhash makes blockhash resolvable by the
247 : status cache when executing transactions on the bank identified by
248 : bank_idx (otherwise the fd_txncache_query/insert FD_TEST(blockcache)
249 : in the executor's pre-execute checks fails). It registers blockhash
250 : on bank_idx's PARENT txncache fork, because a fork can only query
251 : blockhashes registered on a fork it descends from (a fork's
252 : descends-set holds its ancestors, not itself). bank_idx must
253 : therefore have a parent, and that parent fork must not already be
254 : finalized (each txncache fork carries at most one blockhash). */
255 :
256 : void
257 : fd_svm_mini_register_blockhash( fd_svm_mini_t * mini,
258 : ulong bank_idx,
259 : fd_hash_t const * blockhash );
260 :
261 : /* fd_svm_mini_cancel_fork cancels the subtree of the fork graph
262 : identified by bank_idx (i.e. the bank_idx node and all its children,
263 : transitively). */
264 :
265 : void
266 : fd_svm_mini_cancel_fork( fd_svm_mini_t * mini,
267 : ulong bank_idx );
268 :
269 : /* fd_svm_mini_advance_root advances the fork graph root to the node
270 : identified by bank_idx. Cancels all siblings and uncles
271 : (transitively) of the rooted nodes. */
272 :
273 : void
274 : fd_svm_mini_advance_root( fd_svm_mini_t * mini,
275 : ulong bank_idx );
276 :
277 : fd_bank_t *
278 : fd_svm_mini_bank( fd_svm_mini_t * mini,
279 : ulong bank_idx );
280 :
281 : fd_accdb_fork_id_t
282 : fd_svm_mini_fork_id( fd_svm_mini_t * mini,
283 : ulong bank_idx );
284 :
285 : /* Mock/inject API */
286 :
287 : /* fd_svm_mini_put_account_rooted injects a copy of the account at ro
288 : into the rooted state. */
289 :
290 : void
291 : fd_svm_mini_put_account_rooted( fd_svm_mini_t * mini,
292 : fd_acc_t const * ro );
293 :
294 : /* fd_svm_mini_add_lamports_rooted increases the lamport balance of a
295 : rooted accounts. */
296 :
297 : void
298 : fd_svm_mini_add_lamports_rooted( fd_svm_mini_t * mini,
299 : fd_pubkey_t const * pubkey,
300 : ulong lamports );
301 :
302 : /* fd_svm_mini_add_lamports increases the lamport balance of an account. */
303 :
304 : void
305 : fd_svm_mini_add_lamports( fd_svm_mini_t * mini,
306 : fd_accdb_fork_id_t fork_id,
307 : fd_pubkey_t const * pubkey,
308 : ulong lamports );
309 :
310 : FD_PROTOTYPES_END
311 :
312 : #endif /* HEADER_fd_src_flamenco_runtime_tests_fd_svm_mini_h */
|