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