Line data Source code
1 : #ifndef HEADER_fd_discof_restore_fd_snapin_tile_private_h
2 : #define HEADER_fd_discof_restore_fd_snapin_tile_private_h
3 :
4 : /* fd_snapin_tile_private.h contains private APIs for the "snapin" tile,
5 : which is the tile responsible for parsing a snapshot, and directing
6 : database writes. */
7 :
8 : #include "utils/fd_ssparse.h"
9 : #include "utils/fd_ssmanifest_parser.h"
10 : #include "utils/fd_slot_delta_parser.h"
11 : #include "utils/fd_ssctrl.h"
12 : #include "../../flamenco/accdb/fd_accdb_admin.h"
13 : #include "../../flamenco/accdb/fd_accdb_user.h"
14 : #include "../../flamenco/runtime/fd_txncache.h"
15 : #include "../../disco/stem/fd_stem.h"
16 : #include "../../disco/topo/fd_topo.h"
17 : #include "../../vinyl/io/fd_vinyl_io.h"
18 : #include "../../vinyl/meta/fd_vinyl_meta.h"
19 :
20 : struct blockhash_group {
21 : uchar blockhash[ 32UL ];
22 : ulong txnhash_offset;
23 : };
24 :
25 : typedef struct blockhash_group blockhash_group_t;
26 :
27 : struct fd_snapin_out_link {
28 : ulong idx;
29 : fd_wksp_t * mem;
30 : ulong chunk0;
31 : ulong wmark;
32 : ulong chunk;
33 : ulong mtu;
34 : };
35 : typedef struct fd_snapin_out_link fd_snapin_out_link_t;
36 :
37 : struct buffered_account_batch {
38 : uchar const * batch[ FD_SSPARSE_ACC_BATCH_MAX ];
39 : ulong batch_cnt;
40 : ulong slot;
41 : /* index at which to start processing a buffered account batch */
42 : ulong remaining_idx;
43 : };
44 :
45 : typedef struct buffered_account_batch buffered_account_batch_t;
46 :
47 : struct fd_snapin_tile {
48 : int state;
49 : uint full : 1; /* loading a full snapshot? */
50 : uint use_vinyl : 1; /* using vinyl-backed accdb? */
51 : uint lthash_disabled : 1; /* disable lthash checking? */
52 :
53 : ulong seed;
54 : long boot_timestamp;
55 :
56 : fd_accdb_admin_t accdb_admin[1];
57 : fd_accdb_user_t accdb[1];
58 :
59 : fd_txncache_t * txncache;
60 : uchar * acc_data;
61 :
62 : fd_funk_txn_xid_t xid[1]; /* txn XID */
63 :
64 : fd_stem_context_t * stem;
65 :
66 : fd_ssparse_t * ssparse;
67 : fd_ssmanifest_parser_t * manifest_parser;
68 : fd_slot_delta_parser_t * slot_delta_parser;
69 :
70 : buffered_account_batch_t buffered_batch;
71 :
72 : struct {
73 : int manifest_done;
74 : int status_cache_done;
75 : int manifest_processed;
76 : } flags;
77 :
78 : ulong bank_slot;
79 :
80 : ulong blockhash_offsets_len;
81 : blockhash_group_t * blockhash_offsets;
82 :
83 : ulong txncache_entries_len;
84 : fd_sstxncache_entry_t * txncache_entries;
85 :
86 : fd_txncache_fork_id_t txncache_root_fork_id;
87 :
88 : struct {
89 : ulong full_bytes_read;
90 : ulong incremental_bytes_read;
91 : ulong accounts_inserted;
92 : } metrics;
93 :
94 : struct {
95 : fd_wksp_t * wksp;
96 : ulong chunk0;
97 : ulong wmark;
98 : ulong mtu;
99 : ulong pos;
100 : } in;
101 :
102 : ulong out_ct_idx;
103 : fd_snapin_out_link_t manifest_out;
104 : fd_snapin_out_link_t gui_out;
105 : fd_snapin_out_link_t hash_out;
106 :
107 : struct {
108 : uchar * bstream_mem;
109 : ulong bstream_sz;
110 :
111 : /* Vinyl in either io_wd or io_mm mode */
112 : fd_vinyl_io_t * io;
113 : fd_vinyl_io_t * io_wd;
114 : fd_vinyl_io_t * io_mm;
115 : ulong io_seed;
116 :
117 : fd_vinyl_meta_t map[1];
118 :
119 : ulong txn_seq; /* bstream seq of first txn record (in [seq_past,seq_present]) */
120 : uint txn_active : 1;
121 : } vinyl;
122 :
123 : struct {
124 : uchar * pair;
125 : ulong pair_sz;
126 :
127 : uchar * dst;
128 : ulong dst_rem;
129 : ulong data_rem;
130 :
131 : fd_vinyl_meta_ele_t * meta_ele;
132 : } vinyl_op;
133 : };
134 :
135 : typedef struct fd_snapin_tile fd_snapin_tile_t;
136 :
137 : /* Funk APIs **********************************************************/
138 :
139 : FD_PROTOTYPES_BEGIN
140 :
141 : int fd_snapin_process_account_header_funk( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result );
142 : int fd_snapin_process_account_data_funk ( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result );
143 : int fd_snapin_process_account_batch_funk ( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result, buffered_account_batch_t * buffered_batch );
144 :
145 : void
146 : fd_snapin_read_account_funk( fd_snapin_tile_t * ctx,
147 : void const * acct_addr,
148 : fd_account_meta_t * meta,
149 : uchar * data,
150 : ulong data_max );
151 :
152 : FD_PROTOTYPES_END
153 :
154 : /* Vinyl APIs *********************************************************/
155 :
156 : FD_PROTOTYPES_BEGIN
157 :
158 0 : #define FD_SNAPIN_IO_SPAD_MAX (64UL<<20) /* 64 MiB of I/O scratch space */
159 :
160 : /* fd_snapin_vinyl_privileged_init performs administrative tasks, such
161 : as opening and mapping the bstream file descriptor. */
162 :
163 : void
164 : fd_snapin_vinyl_privileged_init( fd_snapin_tile_t * ctx,
165 : fd_topo_t * topo,
166 : fd_topo_tile_t * tile );
167 :
168 : /* fd_snapin_vinyl_unprivileged_init performs setup tasks after being
169 : sandboxed. (anything that might be exposed to untrusted data) */
170 :
171 : void
172 : fd_snapin_vinyl_unprivileged_init( fd_snapin_tile_t * ctx,
173 : fd_topo_t * topo,
174 : fd_topo_tile_t * tile,
175 : void * io_mm_mem,
176 : void * io_wd_mem );
177 :
178 : /* fd_snapin_vinyl_seccomp returns a seccomp sandbox policy suitable
179 : for vinyl operation. */
180 :
181 : ulong
182 : fd_snapin_vinyl_seccomp( ulong out_cnt,
183 : struct sock_filter * out );
184 :
185 : /* fd_snapin_vinyl_reset pauses the snapwr tile (waits for the snapwr
186 : tile to ack) and formats a bstream file to be empty. THIS IS A
187 : DESTRUCTIVE ACTION. */
188 :
189 : void
190 : fd_snapin_vinyl_reset( fd_snapin_tile_t * ctx );
191 :
192 : /* fd_snapin_vinyl_txn_begin starts a transactional burst write.
193 : Assumes vinyl uses the io_mm backend. The write can then either be
194 : committed or cancelled. There is no practical limit on the size of
195 : this burst. */
196 :
197 : void
198 : fd_snapin_vinyl_txn_begin( fd_snapin_tile_t * ctx );
199 :
200 : /* fd_snapin_vinyl_txn_commit finishes a transactional burst write.
201 : Assumes vinyl uses the io_mm backend. Reads through bstream records
202 : written since txn_begin was called and updates the vinyl_meta index. */
203 :
204 : void
205 : fd_snapin_vinyl_txn_commit( fd_snapin_tile_t * ctx );
206 :
207 : /* fd_snapin_vinyl_txn_cancel abandons a transactional burst write.
208 : Assumes vinyl uses the io_mm backend. Reverts the bstream state to
209 : when txn_begin was called. */
210 :
211 : void
212 : fd_snapin_vinyl_txn_cancel( fd_snapin_tile_t * ctx );
213 :
214 : /* fd_snapin_vinyl_wd_init transitions the vinyl backend from generic
215 : vinyl accessor (io_mm) to fast dumb direct account insertion (io_wd).
216 : This must be called before calling fd_snapin_process_account_*.
217 : Starts the snapwr tile (waits for the snapwr tile to ack). */
218 :
219 : void
220 : fd_snapin_vinyl_wd_init( fd_snapin_tile_t * ctx );
221 :
222 : /* fd_snapin_vinyl_wd_fini transitions the vinyl backend from fast dumb
223 : direct account insertion (io_wd) back to generic mode (io_mm).
224 : Pauses the snapwr tile (waits for the snapwr to ack). */
225 :
226 : void
227 : fd_snapin_vinyl_wd_fini( fd_snapin_tile_t * ctx );
228 :
229 : /* fd_snapin_vinyl_shutdown instructs vinyl-related tiles of the loader
230 : to shut down. Blocks until all affected tiles have acknowledged the
231 : shutdown signal. */
232 :
233 : void
234 : fd_snapin_vinyl_shutdown( fd_snapin_tile_t * ctx );
235 :
236 : /* Internal APIs for inserting accounts */
237 :
238 : void fd_snapin_process_account_header_vinyl( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result );
239 : void fd_snapin_process_account_data_vinyl ( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result );
240 : void fd_snapin_process_account_batch_vinyl ( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result );
241 :
242 : void
243 : fd_snapin_read_account_vinyl( fd_snapin_tile_t * ctx,
244 : void const * acct_addr,
245 : fd_account_meta_t * meta,
246 : uchar * data,
247 : ulong data_max );
248 :
249 : FD_PROTOTYPES_END
250 :
251 : /* Generic APIs *******************************************************/
252 :
253 : FD_PROTOTYPES_BEGIN
254 :
255 : /* int return value for fd_snapin_process_account_header,
256 : fd_snapin_process_account_data, and fd_snapin_process_account_batch
257 : indicates whether to yield to stem for credit return */
258 :
259 : static inline int
260 : fd_snapin_process_account_header( fd_snapin_tile_t * ctx,
261 0 : fd_ssparse_advance_result_t * result ) {
262 0 : if( ctx->use_vinyl ) {
263 0 : fd_snapin_process_account_header_vinyl( ctx, result );
264 0 : } else {
265 0 : return fd_snapin_process_account_header_funk( ctx, result );
266 0 : }
267 0 : return 0;
268 0 : }
269 :
270 : static inline int
271 : fd_snapin_process_account_data( fd_snapin_tile_t * ctx,
272 0 : fd_ssparse_advance_result_t * result ) {
273 0 : if( ctx->use_vinyl ) {
274 0 : fd_snapin_process_account_data_vinyl( ctx, result );
275 0 : } else {
276 0 : return fd_snapin_process_account_data_funk( ctx, result );
277 0 : }
278 0 : return 0;
279 0 : }
280 :
281 : static inline int
282 : fd_snapin_process_account_batch( fd_snapin_tile_t * ctx,
283 : fd_ssparse_advance_result_t * result,
284 0 : buffered_account_batch_t * buffered_batch ) {
285 0 : if( ctx->use_vinyl ) {
286 0 : fd_snapin_process_account_batch_vinyl( ctx, result );
287 0 : } else {
288 0 : return fd_snapin_process_account_batch_funk( ctx, result, buffered_batch );
289 0 : }
290 0 : return 0;
291 0 : }
292 :
293 : static inline void
294 : fd_snapin_read_account( fd_snapin_tile_t * ctx,
295 : void const * acct_addr,
296 : fd_account_meta_t * meta,
297 : uchar * data,
298 0 : ulong data_max ) {
299 0 : if( ctx->use_vinyl ) {
300 0 : fd_snapin_read_account_vinyl( ctx, acct_addr, meta, data, data_max );
301 0 : } else {
302 0 : fd_snapin_read_account_funk( ctx, acct_addr, meta, data, data_max );
303 0 : }
304 0 : }
305 :
306 : /* fd_snapin_send_duplicate_account sends a duplicate account message
307 : with the signature FD_SNAPSHOT_HASH_MSG_SUB or
308 : FD_SNAPSHOT_HASH_MSG_SUB_HDR, depending on if this duplicate account
309 : contains valid account data. The message is only
310 : sent if lthash verification is enabled in the snapshot loader.
311 :
312 : lamports is account's lamports value. data is the account's data,
313 : which can be optionally null. data_len is the length of the account
314 : data. executable is the account's executable flag. owner points to
315 : the account's owner (32 bytes). pubkey points to the account's
316 : pubkey (32 bytes). early_exit is an optional pointer to an int flag
317 : that is set to 1 if the caller should yield to stem following this
318 : call. */
319 : static inline void
320 : fd_snapin_send_duplicate_account( fd_snapin_tile_t * ctx,
321 : ulong lamports,
322 : uchar const * data,
323 : ulong data_len,
324 : uchar executable,
325 : uchar const * owner,
326 : uchar const * pubkey,
327 : int has_data,
328 0 : int * early_exit ) {
329 0 : if( FD_UNLIKELY( ctx->lthash_disabled ) ) return;
330 :
331 0 : if( FD_LIKELY( has_data ) ) {
332 0 : fd_snapshot_full_account_t * existing_account = fd_chunk_to_laddr( ctx->hash_out.mem, ctx->hash_out.chunk );
333 0 : fd_snapshot_account_hdr_init( &existing_account->hdr, pubkey, owner, lamports, executable, data_len );
334 0 : fd_memcpy( existing_account->data, data, data_len );
335 0 : fd_stem_publish( ctx->stem, ctx->out_ct_idx, FD_SNAPSHOT_HASH_MSG_SUB, ctx->hash_out.chunk, sizeof(fd_snapshot_account_hdr_t)+data_len, 0UL, 0UL, 0UL );
336 0 : ctx->hash_out.chunk = fd_dcache_compact_next( ctx->hash_out.chunk, sizeof(fd_snapshot_account_hdr_t)+data_len, ctx->hash_out.chunk0, ctx->hash_out.wmark );
337 0 : } else {
338 0 : fd_snapshot_account_hdr_t * acc_hdr = fd_chunk_to_laddr( ctx->hash_out.mem, ctx->hash_out.chunk );
339 0 : fd_snapshot_account_hdr_init( acc_hdr, pubkey, owner, lamports, executable, data_len );
340 0 : fd_stem_publish( ctx->stem, ctx->out_ct_idx, FD_SNAPSHOT_HASH_MSG_SUB_HDR, ctx->hash_out.chunk, sizeof(fd_snapshot_account_hdr_t), 0UL, 0UL, 0UL );
341 0 : ctx->hash_out.chunk = fd_dcache_compact_next( ctx->hash_out.chunk, sizeof(fd_snapshot_account_hdr_t), ctx->hash_out.chunk0, ctx->hash_out.wmark );
342 0 : }
343 0 : if( FD_LIKELY( early_exit ) ) *early_exit = 1;
344 0 : }
345 :
346 : /* fd_snapin_send_duplicate_account_data sends a duplicate account
347 : message with the signature FD_SNAPSHOT_HASH_MSG_SUB_DATA. The
348 : message is only sent if lthash verification is enabled in the
349 : snapshot loader.
350 :
351 : data is the account's data, which cannot be null. data_len is the
352 : length of the account data. early_exit is an optional pointer to an
353 : int flag that is set to 1 if the caller should yield to stem
354 : following this call. */
355 : static inline void
356 : fd_snapin_send_duplicate_account_data( fd_snapin_tile_t * ctx,
357 : uchar const * data,
358 : ulong data_sz,
359 0 : int * early_exit ) {
360 0 : if( FD_UNLIKELY( ctx->lthash_disabled ) ) return;
361 :
362 0 : uchar * drop_account_data = fd_chunk_to_laddr( ctx->hash_out.mem, ctx->hash_out.chunk );
363 0 : fd_memcpy( drop_account_data, data, data_sz );
364 0 : fd_stem_publish( ctx->stem, ctx->out_ct_idx, FD_SNAPSHOT_HASH_MSG_SUB_DATA, ctx->hash_out.chunk, data_sz, 0UL, 0UL, 0UL );
365 0 : ctx->hash_out.chunk = fd_dcache_compact_next( ctx->hash_out.chunk, data_sz, ctx->hash_out.chunk0, ctx->hash_out.wmark );
366 0 : if( FD_LIKELY( early_exit ) ) *early_exit = 1;
367 0 : }
368 :
369 : FD_PROTOTYPES_END
370 :
371 : #endif /* HEADER_fd_discof_restore_fd_snapin_tile_private_h */
|