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