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 bank_slot;
85 :
86 : ulong blockhash_offsets_len;
87 : blockhash_group_t * blockhash_offsets;
88 :
89 : ulong txncache_entries_len;
90 : ulong * txncache_entries_len_vinyl_ptr;
91 : fd_sstxncache_entry_t * txncache_entries;
92 :
93 : fd_txncache_fork_id_t txncache_root_fork_id;
94 :
95 : struct {
96 : ulong full_bytes_read;
97 : ulong incremental_bytes_read;
98 :
99 : /* Account counters (full + incremental) */
100 : ulong accounts_loaded;
101 : ulong accounts_replaced;
102 : ulong accounts_ignored;
103 :
104 : /* Account counters (snapshot taken for full snapshot only) */
105 : ulong full_accounts_loaded;
106 : ulong full_accounts_replaced;
107 : ulong full_accounts_ignored;
108 : } metrics;
109 :
110 : struct {
111 : fd_wksp_t * wksp;
112 : ulong chunk0;
113 : ulong wmark;
114 : ulong mtu;
115 : ulong pos;
116 : } in;
117 :
118 : ulong out_ct_idx;
119 : fd_snapin_out_link_t manifest_out;
120 : fd_snapin_out_link_t gui_out;
121 : fd_snapin_out_link_t hash_out;
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 : #define FD_SNAPIN_IO_SPAD_MAX (64UL<<20) /* 64 MiB of I/O scratch space */
159 :
160 : /* fd_snapin_vinyl_unprivileged_init performs setup tasks after being
161 : sandboxed. (anything that might be exposed to untrusted data) */
162 :
163 : void
164 : fd_snapin_vinyl_unprivileged_init( fd_snapin_tile_t * ctx,
165 : fd_topo_t * topo,
166 : fd_topo_tile_t * tile,
167 : void * io_mm_mem,
168 : void * io_wd_mem );
169 :
170 : /* fd_snapin_vinyl_seccomp returns a seccomp sandbox policy suitable
171 : for vinyl operation. */
172 :
173 : ulong
174 : fd_snapin_vinyl_seccomp( ulong out_cnt,
175 : struct sock_filter * out );
176 :
177 : /* fd_snapin_vinyl_reset pauses the snapwr tile (waits for the snapwr
178 : tile to ack) and formats a bstream file to be empty. THIS IS A
179 : DESTRUCTIVE ACTION. */
180 :
181 : void
182 : fd_snapin_vinyl_reset( fd_snapin_tile_t * ctx );
183 :
184 : /* fd_snapin_vinyl_txn_begin starts a transactional burst write.
185 : Assumes vinyl uses the io_mm backend. The write can then either be
186 : committed or cancelled. There is no practical limit on the size of
187 : this burst. */
188 :
189 : void
190 : fd_snapin_vinyl_txn_begin( fd_snapin_tile_t * ctx );
191 :
192 : /* fd_snapin_vinyl_txn_commit finishes a transactional burst write.
193 : Assumes vinyl uses the io_mm backend. Reads through bstream records
194 : written since txn_begin was called and updates the vinyl_meta index. */
195 :
196 : void
197 : fd_snapin_vinyl_txn_commit( fd_snapin_tile_t * ctx );
198 :
199 : /* fd_snapin_vinyl_txn_cancel abandons a transactional burst write.
200 : Assumes vinyl uses the io_mm backend. Reverts the bstream state to
201 : when txn_begin was called. */
202 :
203 : void
204 : fd_snapin_vinyl_txn_cancel( fd_snapin_tile_t * ctx );
205 :
206 : /* fd_snapin_vinyl_wd_init transitions the vinyl backend from generic
207 : vinyl accessor (io_mm) to fast dumb direct account insertion (io_wd).
208 : This must be called before calling fd_snapin_process_account_*.
209 : Starts the snapwr tile (waits for the snapwr tile to ack). */
210 :
211 : void
212 : fd_snapin_vinyl_wd_init( fd_snapin_tile_t * ctx );
213 :
214 : /* fd_snapin_vinyl_wd_fini transitions the vinyl backend from fast dumb
215 : direct account insertion (io_wd) back to generic mode (io_mm).
216 : Pauses the snapwr tile (waits for the snapwr to ack). */
217 :
218 : void
219 : fd_snapin_vinyl_wd_fini( fd_snapin_tile_t * ctx );
220 :
221 : /* fd_snapin_vinyl_shutdown instructs vinyl-related tiles of the loader
222 : to shut down. Blocks until all affected tiles have acknowledged the
223 : shutdown signal. */
224 :
225 : void
226 : fd_snapin_vinyl_shutdown( fd_snapin_tile_t * ctx );
227 :
228 : /* Internal APIs for inserting accounts */
229 :
230 : int fd_snapin_process_account_header_vinyl( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result );
231 : int fd_snapin_process_account_data_vinyl ( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result );
232 : int fd_snapin_process_account_batch_vinyl ( fd_snapin_tile_t * ctx, fd_ssparse_advance_result_t * result );
233 :
234 : FD_PROTOTYPES_END
235 :
236 : /* Generic APIs *******************************************************/
237 :
238 : FD_PROTOTYPES_BEGIN
239 :
240 : /* int return value for fd_snapin_process_account_header,
241 : fd_snapin_process_account_data, and fd_snapin_process_account_batch
242 : indicates whether to yield to stem for credit return */
243 :
244 : static inline int
245 : fd_snapin_process_account_header( fd_snapin_tile_t * ctx,
246 0 : fd_ssparse_advance_result_t * result ) {
247 0 : if( ctx->use_vinyl ) {
248 0 : return fd_snapin_process_account_header_vinyl( ctx, result );
249 0 : } else {
250 0 : return fd_snapin_process_account_header_funk( ctx, result );
251 0 : }
252 0 : return 0;
253 0 : }
254 :
255 : static inline int
256 : fd_snapin_process_account_data( fd_snapin_tile_t * ctx,
257 0 : fd_ssparse_advance_result_t * result ) {
258 0 : if( ctx->use_vinyl ) {
259 0 : return fd_snapin_process_account_data_vinyl( ctx, result );
260 0 : } else {
261 0 : return fd_snapin_process_account_data_funk( ctx, result );
262 0 : }
263 0 : return 0;
264 0 : }
265 :
266 : static inline int
267 : fd_snapin_process_account_batch( fd_snapin_tile_t * ctx,
268 : fd_ssparse_advance_result_t * result,
269 0 : buffered_account_batch_t * buffered_batch ) {
270 0 : if( ctx->use_vinyl ) {
271 0 : return fd_snapin_process_account_batch_vinyl( ctx, result );
272 0 : } else {
273 0 : return fd_snapin_process_account_batch_funk( ctx, result, buffered_batch );
274 0 : }
275 0 : return 0;
276 0 : }
277 :
278 : static inline void
279 : fd_snapin_read_account( fd_snapin_tile_t * ctx,
280 : void const * acct_addr,
281 : fd_account_meta_t * meta,
282 : uchar * data,
283 0 : ulong data_max ) {
284 : /* fd_snapin_read_account will no longer be required in the snapin
285 : tile once funk is deprecated from the snapshot load pipeline.
286 : Under vinyl, this is implemented in the snapwm tile. */
287 0 : if( ctx->use_vinyl ) {
288 0 : FD_LOG_ERR(( "read account is not supported under vinyl" ));
289 0 : } else {
290 0 : fd_snapin_read_account_funk( ctx, acct_addr, meta, data, data_max );
291 0 : }
292 0 : }
293 :
294 : /* fd_snapin_send_duplicate_account sends a duplicate account message
295 : with the signature FD_SNAPSHOT_HASH_MSG_SUB or
296 : FD_SNAPSHOT_HASH_MSG_SUB_HDR, depending on if this duplicate account
297 : contains valid account data. The message is only
298 : sent if lthash verification is enabled in the snapshot loader.
299 :
300 : lamports is account's lamports value. data is the account's data,
301 : which can be optionally null. data_len is the length of the account
302 : data. executable is the account's executable flag. owner points to
303 : the account's owner (32 bytes). pubkey points to the account's
304 : pubkey (32 bytes). early_exit is an optional pointer to an int flag
305 : that is set to 1 if the caller should yield to stem following this
306 : call. */
307 : static inline void
308 : fd_snapin_send_duplicate_account( fd_snapin_tile_t * ctx,
309 : ulong lamports,
310 : uchar const * data,
311 : ulong data_len,
312 : uchar executable,
313 : uchar const * owner,
314 : uchar const * pubkey,
315 : int has_data,
316 0 : int * early_exit ) {
317 0 : if( FD_UNLIKELY( ctx->lthash_disabled ) ) return;
318 :
319 0 : if( FD_LIKELY( has_data ) ) {
320 0 : fd_snapshot_full_account_t * existing_account = fd_chunk_to_laddr( ctx->hash_out.mem, ctx->hash_out.chunk );
321 0 : fd_snapshot_account_hdr_init( &existing_account->hdr, pubkey, owner, lamports, executable, data_len );
322 0 : fd_memcpy( existing_account->data, data, data_len );
323 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 );
324 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 );
325 0 : } else {
326 0 : fd_snapshot_account_hdr_t * acc_hdr = fd_chunk_to_laddr( ctx->hash_out.mem, ctx->hash_out.chunk );
327 0 : fd_snapshot_account_hdr_init( acc_hdr, pubkey, owner, lamports, executable, data_len );
328 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 );
329 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 );
330 0 : }
331 0 : if( FD_LIKELY( early_exit ) ) *early_exit = 1;
332 0 : }
333 :
334 : /* fd_snapin_send_duplicate_account_data sends a duplicate account
335 : message with the signature FD_SNAPSHOT_HASH_MSG_SUB_DATA. The
336 : message is only sent if lthash verification is enabled in the
337 : snapshot loader.
338 :
339 : data is the account's data, which cannot be null. data_len is the
340 : length of the account data. early_exit is an optional pointer to an
341 : int flag that is set to 1 if the caller should yield to stem
342 : following this call. */
343 : static inline void
344 : fd_snapin_send_duplicate_account_data( fd_snapin_tile_t * ctx,
345 : uchar const * data,
346 : ulong data_sz,
347 0 : int * early_exit ) {
348 0 : if( FD_UNLIKELY( ctx->lthash_disabled ) ) return;
349 :
350 0 : uchar * drop_account_data = fd_chunk_to_laddr( ctx->hash_out.mem, ctx->hash_out.chunk );
351 0 : fd_memcpy( drop_account_data, data, data_sz );
352 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 );
353 0 : ctx->hash_out.chunk = fd_dcache_compact_next( ctx->hash_out.chunk, data_sz, ctx->hash_out.chunk0, ctx->hash_out.wmark );
354 0 : if( FD_LIKELY( early_exit ) ) *early_exit = 1;
355 0 : }
356 :
357 : FD_PROTOTYPES_END
358 :
359 : #endif /* HEADER_fd_discof_restore_fd_snapin_tile_private_h */
|