Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_runtime_fd_blockstore_h
2 : #define HEADER_fd_src_flamenco_runtime_fd_blockstore_h
3 :
4 : /* Blockstore is a high-performance database for storing, building, and tracking blocks.
5 :
6 : `fd_blockstore` defines a number of useful types e.g. `fd_block_t`, `fd_block_shred`, etc. */
7 :
8 : #include "../../ballet/block/fd_microblock.h"
9 : #include "../../ballet/shred/fd_deshredder.h"
10 : #include "../../ballet/shred/fd_shred.h"
11 : #include "../fd_flamenco_base.h"
12 : #include "../types/fd_types.h"
13 : #include "fd_rwseq_lock.h"
14 : #include "stdbool.h"
15 :
16 : /* FD_BLOCKSTORE_{ALIGN,FOOTPRINT} describe the alignment and footprint needed
17 : for a blockstore. ALIGN should be a positive integer power of 2.
18 : FOOTPRINT is multiple of ALIGN. These are provided to facilitate
19 : compile time declarations. */
20 :
21 : /* clang-format off */
22 : #define FD_BLOCKSTORE_ALIGN (128UL)
23 : #define FD_BLOCKSTORE_FOOTPRINT (256UL)
24 0 : #define FD_BLOCKSTORE_MAGIC (0xf17eda2ce7b10c00UL) /* firedancer bloc version 0 */
25 :
26 : /* DO NOT MODIFY. */
27 : #define FD_BUF_SHRED_MAP_MAX (1UL << 24UL) /* 16 million shreds can be buffered */
28 : #define FD_TXN_MAP_LG_MAX (24) /* 16 million txns can be stored in the txn map */
29 :
30 : /* TODO this can be removed if we explicitly manage a memory pool for
31 : the fd_block_map_t entries */
32 0 : #define FD_BLOCKSTORE_CHILD_SLOT_MAX (32UL) /* the maximum # of children a slot can have */
33 :
34 : // TODO centralize these
35 : // https://github.com/firedancer-io/solana/blob/v1.17.5/sdk/program/src/clock.rs#L34
36 : #define FD_MS_PER_TICK 6
37 :
38 : // https://github.com/firedancer-io/solana/blob/v1.17.5/core/src/repair/repair_service.rs#L55
39 : #define FD_REPAIR_TIMEOUT (200 / FD_MS_PER_TICK)
40 :
41 0 : #define FD_BLOCKSTORE_OK 0
42 0 : #define FD_BLOCKSTORE_OK_SLOT_COMPLETE 1
43 : #define FD_BLOCKSTORE_ERR_SHRED_FULL -1 /* no space left for shreds */
44 0 : #define FD_BLOCKSTORE_ERR_SLOT_FULL -2 /* no space left for slots */
45 : #define FD_BLOCKSTORE_ERR_TXN_FULL -3 /* no space left for txns */
46 : #define FD_BLOCKSTORE_ERR_SHRED_MISSING -4
47 0 : #define FD_BLOCKSTORE_ERR_SLOT_MISSING -5
48 0 : #define FD_BLOCKSTORE_ERR_TXN_MISSING -6
49 0 : #define FD_BLOCKSTORE_ERR_SHRED_INVALID -7 /* shred was invalid */
50 0 : #define FD_BLOCKSTORE_ERR_DESHRED_INVALID -8 /* deshredded block was invalid */
51 0 : #define FD_BLOCKSTORE_ERR_NO_MEM -9 /* no mem */
52 0 : #define FD_BLOCKSTORE_ERR_UNKNOWN -99
53 :
54 : /* clang-format on */
55 :
56 : struct fd_shred_key {
57 : ulong slot;
58 : uint idx;
59 : };
60 : typedef struct fd_shred_key fd_shred_key_t;
61 :
62 : /* clang-format off */
63 : static const fd_shred_key_t fd_shred_key_null = { 0 };
64 : #define FD_SHRED_KEY_NULL fd_shred_key_null
65 : #define FD_SHRED_KEY_INVAL(key) (!((key).slot) & !((key).idx))
66 0 : #define FD_SHRED_KEY_EQ(k0,k1) (!(((k0).slot) ^ ((k1).slot))) & !(((k0).idx) ^ (((k1).idx)))
67 0 : #define FD_SHRED_KEY_HASH(key) ((uint)(((key).slot)<<15UL) | (((key).idx))) /* current max shred idx is 32KB = 2 << 15*/
68 : /* clang-format on */
69 :
70 : /* fd_buf_shred is a thin wrapper around fd_shred_t that facilitates
71 : buffering data shreds before all the shreds for a slot have been
72 : received. After all shreds are received, these buffered shreds are
73 : released back into memory pool and future queries for the shreds are
74 : offset into the block data directly.
75 :
76 : The blockstore is only aware of data shreds and all APIs involving
77 : shreds refers to data shreds.
78 :
79 : Shreds are buffered into a map as they are received:
80 :
81 : | 0 | 1 | 2 | x | x | 5 | x |
82 : ^ ^
83 : c r
84 :
85 : c = "consumed" = contiguous window starting from index 0
86 : r = "received" = highest index received so far
87 :
88 : Shred memory layout while stored in the map:
89 :
90 : | shred hdr | shred payload |
91 : */
92 : struct fd_buf_shred {
93 : fd_shred_key_t key;
94 : ulong next;
95 : union {
96 : fd_shred_t hdr; /* data shred header */
97 : uchar raw[FD_SHRED_MAX_SZ]; /* the data shred as raw bytes, both header and payload. */
98 : };
99 : };
100 : typedef struct fd_buf_shred fd_buf_shred_t;
101 :
102 : #define POOL_NAME fd_buf_shred_pool
103 0 : #define POOL_T fd_buf_shred_t
104 : #include "../../util/tmpl/fd_pool.c"
105 :
106 : /* clang-format off */
107 : #define MAP_NAME fd_buf_shred_map
108 : #define MAP_ELE_T fd_buf_shred_t
109 : #define MAP_KEY_T fd_shred_key_t
110 0 : #define MAP_KEY_EQ(k0,k1) (FD_SHRED_KEY_EQ(*k0,*k1))
111 0 : #define MAP_KEY_HASH(key,seed) (FD_SHRED_KEY_HASH(*key)^seed)
112 : #include "../../util/tmpl/fd_map_chain.c"
113 : /* clang-format on */
114 :
115 : #define DEQUE_NAME fd_blockstore_slot_deque
116 0 : #define DEQUE_T ulong
117 : #include "../../util/tmpl/fd_deque_dynamic.c"
118 :
119 : /* A shred that has been deshredded and is part of a block (beginning at off) */
120 : struct fd_block_shred {
121 : fd_shred_t hdr; /* ptr to the data shred header */
122 : uchar merkle[FD_SHRED_MERKLE_ROOT_SZ + FD_SHRED_MERKLE_NODE_SZ*9U /* FD_FEC_SET_MAX_BMTREE_DEPTH */];
123 : ulong merkle_sz;
124 : ulong off; /* offset to the payload relative to the start of the block's data region */
125 : };
126 : typedef struct fd_block_shred fd_block_shred_t;
127 :
128 : /* A microblock (otherwise known as an "entry" in Solana parlance) that has been parsed and is part
129 : of a block (beginning at off) */
130 : struct fd_block_micro {
131 : ulong off; /* offset into block data */
132 : };
133 : typedef struct fd_block_micro fd_block_micro_t;
134 :
135 : /* A transaction that has been parsed and is part of a block (beginning at txn_off) */
136 : struct fd_block_txn_ref {
137 : ulong txn_off; /* offset into block data of transaction */
138 : ulong id_off; /* offset into block data of transaction identifiers */
139 : ulong sz;
140 : };
141 : typedef struct fd_block_txn_ref fd_block_txn_ref_t;
142 :
143 : /* If the 0th bit is set, this indicates the block is preparing, which
144 : means it might be partially executed e.g. a subset of the microblocks
145 : have been executed. It is not safe to remove, relocate, or modify
146 : the block in any way at this time.
147 :
148 : Callers holding a pointer to a block should always make sure to
149 : inspect this flag.
150 :
151 : Other flags mainly provide useful metadata for read-only callers, eg.
152 : RPC. */
153 :
154 0 : #define FD_BLOCK_FLAG_SHREDDING 0 /* xxxxxxx1 still receiving shreds */
155 0 : #define FD_BLOCK_FLAG_COMPLETED 1 /* xxxxxx1x received all shreds (DATA_COMPLETE) */
156 0 : #define FD_BLOCK_FLAG_REPLAYING 2 /* xxxxx1xx replay in progress (DO NOT REMOVE) */
157 0 : #define FD_BLOCK_FLAG_PROCESSED 3 /* xxxx1xxx successfully replayed the block */
158 0 : #define FD_BLOCK_FLAG_EQVOCSAFE 4 /* xxxx1xxx 52% of cluster has voted on this (slot, bank hash) */
159 0 : #define FD_BLOCK_FLAG_CONFIRMED 5 /* xxx1xxxx 2/3 of cluster has voted on this (slot, bank hash) */
160 0 : #define FD_BLOCK_FLAG_FINALIZED 6 /* xx1xxxxx 2/3 of cluster has rooted this slot */
161 : #define FD_BLOCK_FLAG_DEADBLOCK 7 /* x1xxxxxx failed to replay the block */
162 :
163 : /* Rewards assigned after block is executed */
164 :
165 : struct fd_block_rewards {
166 : ulong collected_fees;
167 : fd_hash_t leader;
168 : ulong post_balance;
169 : };
170 : typedef struct fd_block_rewards fd_block_rewards_t;
171 :
172 : /* Remaining bits [4, 8) are reserved.
173 :
174 : To avoid confusion, please use `fd_bits.h` API
175 : ie. `fd_uchar_set_bit`, `fd_uchar_extract_bit`. */
176 :
177 : struct fd_block {
178 :
179 : /* Computed rewards */
180 :
181 : fd_block_rewards_t rewards;
182 :
183 : /* data region
184 :
185 : A block's data region is indexed to support iterating by shred, microblock, or
186 : transaction. This is done by iterating the headers for each, stored in allocated memory. To
187 : iterate shred payloads, for example, a caller should iterate the headers in tandem with the data region
188 : (offsetting by the bytes indicated in the shred header).
189 :
190 : Note random access of individual shred indices is not performant, due to the variable-length
191 : nature of shreds. */
192 :
193 : ulong data_gaddr; /* ptr to the beginning of the block's allocated data region */
194 : ulong data_sz; /* block size */
195 : ulong shreds_gaddr; /* ptr to the first fd_block_shred_t */
196 : ulong shreds_cnt;
197 : ulong micros_gaddr; /* ptr to the list of fd_blockstore_micro_t */
198 : ulong micros_cnt;
199 : ulong txns_gaddr; /* ptr to the list of fd_blockstore_txn_ref_t */
200 : ulong txns_cnt;
201 : ulong txns_meta_gaddr; /* ptr to the allocation for txn meta data */
202 : ulong txns_meta_sz;
203 : };
204 : typedef struct fd_block fd_block_t;
205 :
206 : struct fd_block_map {
207 : ulong slot; /* map key */
208 : ulong next; /* reserved for use by fd_map_giant.c */
209 :
210 : /* Ancestry */
211 :
212 : ulong parent_slot;
213 : ulong child_slots[FD_BLOCKSTORE_CHILD_SLOT_MAX];
214 : ulong child_slot_cnt;
215 :
216 : /* Metadata */
217 :
218 : ulong height;
219 : fd_hash_t block_hash;
220 : fd_hash_t bank_hash;
221 : uchar flags;
222 : uchar reference_tick; /* the tick when the leader prepared the block. */
223 : long ts; /* the wallclock time when we finished receiving the block. */
224 :
225 : /* Windowing */
226 :
227 : uint consumed_idx; /* the highest shred idx of the contiguous window from idx 0 (inclusive). */
228 : uint received_idx; /* the highest shred idx we've received (exclusive). */
229 : uint complete_idx; /* the shred idx with the FD_SHRED_DATA_FLAG_SLOT_COMPLETE flag set. */
230 :
231 : /* Block */
232 :
233 : ulong block_gaddr; /* global address to the start of the allocated fd_block_t */
234 : };
235 : typedef struct fd_block_map fd_block_map_t;
236 :
237 : /* clang-format off */
238 : #define MAP_NAME fd_block_map
239 0 : #define MAP_T fd_block_map_t
240 0 : #define MAP_KEY slot
241 : #include "../../util/tmpl/fd_map_giant.c"
242 : /* clang-format on */
243 :
244 : struct fd_blockstore_txn_key {
245 : ulong v[FD_ED25519_SIG_SZ / sizeof( ulong )];
246 : };
247 : typedef struct fd_blockstore_txn_key fd_blockstore_txn_key_t;
248 :
249 : struct fd_blockstore_txn_map {
250 : fd_blockstore_txn_key_t sig;
251 : ulong next;
252 : ulong slot;
253 : ulong offset;
254 : ulong sz;
255 : ulong meta_gaddr; /* ptr to the transaction metadata */
256 : ulong meta_sz; /* metadata size */
257 : };
258 : typedef struct fd_blockstore_txn_map fd_blockstore_txn_map_t;
259 :
260 : /* clang-format off */
261 : #define MAP_NAME fd_blockstore_txn_map
262 0 : #define MAP_T fd_blockstore_txn_map_t
263 0 : #define MAP_KEY sig
264 : #define MAP_KEY_T fd_blockstore_txn_key_t
265 : int fd_blockstore_txn_key_equal(fd_blockstore_txn_key_t const * k0, fd_blockstore_txn_key_t const * k1);
266 0 : #define MAP_KEY_EQ(k0,k1) fd_blockstore_txn_key_equal(k0,k1)
267 : ulong fd_blockstore_txn_key_hash(fd_blockstore_txn_key_t const * k, ulong seed);
268 0 : #define MAP_KEY_HASH(k,seed) fd_blockstore_txn_key_hash(k, seed)
269 : #include "../../util/tmpl/fd_map_giant.c"
270 :
271 : // TODO make this private
272 : struct __attribute__((aligned(FD_BLOCKSTORE_ALIGN))) fd_blockstore_private {
273 :
274 : /* Metadata */
275 :
276 : ulong magic;
277 : ulong blockstore_gaddr;
278 : ulong wksp_tag;
279 : ulong seed;
280 :
281 : /* Concurrency */
282 :
283 : fd_rwseq_lock_t lock;
284 :
285 : /* Slot metadata */
286 :
287 : ulong min; /* minimum slot in the blockstore with a block. we retain
288 : blocks prior to the smr to serve repair and RPC */
289 : ulong max; /* maximum slot in the blockstore with a block */
290 : ulong lps; /* latest processed slot */
291 : ulong hcs; /* highest confirmed slot */
292 : ulong smr; /* supermajority root. DO NOT MODIFY DIRECTLY, instead use fd_blockstore_publish */
293 :
294 : /* Internal data structures */
295 :
296 : ulong shred_max; /* max number of temporary shreds */
297 : ulong shred_pool_gaddr; /* pool of temporary shreds */
298 : ulong shred_map_gaddr; /* map of (slot, shred_idx)->shred */
299 :
300 : ulong slot_max; /* maximum # of blocks */
301 : ulong slot_map_gaddr; /* map of slot->(slot_meta, block) */
302 : ulong slot_deque_gaddr; /* deque of slots (ulongs) used to traverse blockstore ancestry */
303 :
304 : ulong lg_txn_max;
305 : ulong txn_map_gaddr;
306 :
307 : /* The blockstore alloc is used for allocating wksp resources for shred headers, microblock
308 : headers, and blocks. This is an fd_alloc. Allocations from this allocator will be tagged with
309 : wksp_tag and operations on this allocator will use concurrency group 0. */
310 :
311 : ulong alloc_gaddr;
312 : };
313 : /* clang-format on */
314 :
315 : struct fd_blockstore_private;
316 : typedef struct fd_blockstore_private fd_blockstore_t;
317 :
318 : FD_PROTOTYPES_BEGIN
319 :
320 : /* Construction API */
321 :
322 : /* TODO document lifecycle methods */
323 :
324 : FD_FN_CONST ulong
325 : fd_blockstore_align( void );
326 :
327 : FD_FN_CONST ulong
328 : fd_blockstore_footprint( void );
329 :
330 : void *
331 : fd_blockstore_new( void * shmem,
332 : ulong wksp_tag,
333 : ulong seed,
334 : ulong shred_max,
335 : ulong slot_max,
336 : ulong lg_txn_max );
337 :
338 : fd_blockstore_t *
339 : fd_blockstore_join( void * shblockstore );
340 :
341 : void *
342 : fd_blockstore_leave( fd_blockstore_t * blockstore );
343 :
344 : void *
345 : fd_blockstore_delete( void * shblockstore );
346 :
347 : /* fd_blockstore_init initializes a blockstore with slot_bank. slot_bank
348 : should be the bank upon finishing a snapshot load if booting from a
349 : snapshot, genesis bank otherwise. Blockstore then initializes fields
350 : and creates a mock block using this slot bank. This metadata for
351 : this block's slot will be populated (fd_block_map_t) but the actual
352 : block data (fd_block_t) won't exist. This is needed to bootstrap the
353 : various componenets for live replay (turbine, repair, etc.) */
354 :
355 : fd_blockstore_t *
356 : fd_blockstore_init( fd_blockstore_t * blockstore, fd_slot_bank_t const * slot_bank );
357 :
358 : /* Accessor API */
359 :
360 : /* fd_blockstore_wksp returns the local join to the wksp backing the
361 : blockstore. The lifetime of the returned pointer is at least as long
362 : as the lifetime of the local join. Assumes blockstore is a current
363 : local join. */
364 :
365 : FD_FN_PURE static inline fd_wksp_t *
366 0 : fd_blockstore_wksp( fd_blockstore_t * blockstore ) {
367 0 : return (fd_wksp_t *)( ( (ulong)blockstore ) - blockstore->blockstore_gaddr );
368 0 : }
369 :
370 : /* fd_blockstore_wksp_tag returns the workspace allocation tag used by
371 : the blockstore for its wksp allocations. Will be positive. Assumes
372 : blockstore is a current local join. */
373 :
374 : FD_FN_PURE static inline ulong
375 0 : fd_blockstore_wksp_tag( fd_blockstore_t * blockstore ) {
376 0 : return blockstore->wksp_tag;
377 0 : }
378 :
379 : /* fd_blockstore_seed returns the hash seed used by the blockstore for various hash
380 : functions. Arbitrary value. Assumes blockstore is a current local join.
381 : TODO: consider renaming hash_seed? */
382 : FD_FN_PURE static inline ulong
383 0 : fd_blockstore_seed( fd_blockstore_t * blockstore ) {
384 0 : return blockstore->seed;
385 0 : }
386 :
387 : /* fd_blockstore_buf_shred_pool returns a pointer in the caller's
388 : address space to the pool pointer fd_buf_shred_t * in the blockstore
389 : wksp. Assumes blockstore is local join. Lifetime of the returned
390 : pointer is that of the local join. */
391 :
392 : FD_FN_PURE static inline fd_buf_shred_t *
393 0 : fd_blockstore_buf_shred_pool( fd_blockstore_t * blockstore ) {
394 0 : return (fd_buf_shred_t *)fd_wksp_laddr_fast( fd_blockstore_wksp( blockstore ),
395 0 : blockstore->shred_pool_gaddr );
396 0 : }
397 :
398 : /* fd_blockstore_buf_shred_map returns a pointer in the caller's address
399 : space to the fd_buf_shred_map_t * in the blockstore wksp. Assumes
400 : blockstore is local join. Lifetime of the returned pointer is that
401 : of the local join. */
402 :
403 : FD_FN_PURE static inline fd_buf_shred_map_t *
404 0 : fd_blockstore_buf_shred_map( fd_blockstore_t * blockstore ) {
405 0 : return (fd_buf_shred_map_t *)fd_wksp_laddr_fast( fd_blockstore_wksp( blockstore ),
406 0 : blockstore->shred_map_gaddr );
407 0 : }
408 :
409 : /* fd_block_map returns a pointer in the caller's address space to the
410 : fd_block_map_t in the blockstore wksp. Assumes blockstore is local
411 : join. Lifetime of the returned pointer is that of the local join. */
412 : FD_FN_PURE static inline fd_block_map_t *
413 0 : fd_blockstore_block_map( fd_blockstore_t * blockstore ) {
414 0 : return (fd_block_map_t *)fd_wksp_laddr_fast( fd_blockstore_wksp( blockstore ),
415 0 : blockstore->slot_map_gaddr );
416 0 : }
417 :
418 : /* fd_blockstore_txn_map returns a pointer in the caller's address space to the blockstore's
419 : block map. Assumes blockstore is local join. Lifetime of the returned pointer is that of the
420 : local join. */
421 :
422 : FD_FN_PURE static inline fd_blockstore_txn_map_t *
423 0 : fd_blockstore_txn_map( fd_blockstore_t * blockstore ) {
424 0 : return (fd_blockstore_txn_map_t *)fd_wksp_laddr_fast( fd_blockstore_wksp( blockstore ),
425 0 : blockstore->txn_map_gaddr );
426 0 : }
427 :
428 : /* fd_blockstore_alloc returns a pointer in the caller's address space to
429 : the blockstore's allocator. */
430 :
431 : FD_FN_PURE static inline fd_alloc_t * /* Lifetime is that of the local join */
432 0 : fd_blockstore_alloc( fd_blockstore_t * blockstore ) {
433 0 : return (fd_alloc_t *)fd_wksp_laddr_fast( fd_blockstore_wksp( blockstore ),
434 0 : blockstore->alloc_gaddr );
435 0 : }
436 :
437 : /* fd_blockstore_block_data_laddr returns a local pointer to the block's data. The returned pointer
438 : * lifetime is until the block is removed. Check return value for error info. */
439 :
440 : FD_FN_PURE static inline uchar *
441 0 : fd_blockstore_block_data_laddr( fd_blockstore_t * blockstore, fd_block_t * block ) {
442 0 : return fd_wksp_laddr_fast( fd_blockstore_wksp( blockstore ), block->data_gaddr );
443 0 : }
444 :
445 : FD_FN_PURE static inline ulong
446 0 : fd_blockstore_block_cnt( fd_blockstore_t * blockstore ) {
447 0 : return blockstore->max - blockstore->min + 1;
448 0 : }
449 :
450 : /* Operations */
451 :
452 : /* Insert shred into the blockstore, fast O(1). Fail if this shred is already in the blockstore or
453 : * the blockstore is full. Returns an error code indicating success or failure.
454 : *
455 : * TODO eventually this will need to support "upsert" duplicate shred handling.
456 : */
457 : int
458 : fd_buf_shred_insert( fd_blockstore_t * blockstore, fd_shred_t const * shred );
459 :
460 : /* Query blockstore for shred at slot, shred_idx. Returns a pointer to the shred or NULL if not in
461 : * blockstore. The returned pointer lifetime is until the shred is removed. Check return value for
462 : * error info. This API only works for shreds from incomplete blocks.
463 : *
464 : * Callers should hold the read lock during the entirety of its read to ensure the pointer remains
465 : * valid.
466 : */
467 : fd_shred_t *
468 : fd_buf_shred_query( fd_blockstore_t * blockstore, ulong slot, uint shred_idx );
469 :
470 : /* Query blockstore for shred at slot, shred_idx. Copies the shred
471 : * data to the given buffer and returns the data size. Returns -1 on failure.
472 : *
473 : * Callers should hold the read lock during the entirety of this call.
474 : */
475 : long
476 : fd_buf_shred_query_copy_data( fd_blockstore_t * blockstore,
477 : ulong slot,
478 : uint shred_idx,
479 : void * buf,
480 : ulong buf_max );
481 :
482 : /* Query blockstore for block at slot. Returns a pointer to the block or NULL if not in
483 : * blockstore. The returned pointer lifetime is until the block is removed. Check return value for
484 : * error info. */
485 : fd_block_t *
486 : fd_blockstore_block_query( fd_blockstore_t * blockstore, ulong slot );
487 :
488 : /* Query blockstore for the block hash at slot. This is the final poh
489 : hash for a slot. */
490 : fd_hash_t const *
491 : fd_blockstore_block_hash_query( fd_blockstore_t * blockstore, ulong slot );
492 :
493 : /* Query blockstore for the bank hash for a given slot. */
494 : fd_hash_t const *
495 : fd_blockstore_bank_hash_query( fd_blockstore_t * blockstore, ulong slot );
496 :
497 : /* Query blockstore for the block map entry at slot. Returns a pointer
498 : to the slot meta or NULL if not in blockstore. The returned pointer
499 : lifetime is until the slot meta is removed. */
500 : fd_block_map_t *
501 : fd_blockstore_block_map_query( fd_blockstore_t * blockstore, ulong slot );
502 :
503 : /* Query the parent slot of slot. */
504 : ulong
505 : fd_blockstore_parent_slot_query( fd_blockstore_t * blockstore, ulong slot );
506 :
507 : /* fd_blockstore_child_slots_query queries slot's child slots. Return
508 : values are saved in slots_out and slot_cnt. Returns FD_BLOCKSTORE_OK
509 : on success, FD_BLOCKSTORE_ERR_SLOT_MISSING if slot is not in the
510 : blockstore. The returned slot array is always <= the max size
511 : FD_BLOCKSTORE_CHILD_SLOT_MAX and contiguous. Empty slots in the
512 : array are set to FD_SLOT_NULL. */
513 :
514 : int
515 : fd_blockstore_child_slots_query( fd_blockstore_t * blockstore, ulong slot, ulong ** slots_out, ulong * slot_cnt );
516 :
517 : /* Query the frontier ie. all the blocks that need to be replayed that haven't been. These are the
518 : slot children of the current frontier that are shred complete. */
519 : fd_block_t *
520 : fd_blockstore_block_frontier_query( fd_blockstore_t * blockstore,
521 : ulong * parents,
522 : ulong parents_sz );
523 :
524 : /* fd_blockstore_block_data_query_volatile queries the block map entry
525 : (metadata and block data) in a lock-free thread-safe manner that does
526 : not block writes. Copies the metadata (fd_block_map_t) into
527 : block_map_entry_out. Allocates a new block data (uchar *) using
528 : alloc, copies the block data into it, and sets the block_data_out
529 : pointer. Caller provides the allocator via alloc for the copied
530 : block data (an allocator is needed because the block data sz is not
531 : known apriori). Returns FD_BLOCKSTORE_SLOT_MISSING if slot is
532 : missing: caller MUST ignore out pointers in this case. Otherwise this
533 : call cannot fail and returns FD_BLOCKSTORE_OK. */
534 :
535 : int
536 : fd_blockstore_block_data_query_volatile( fd_blockstore_t * blockstore, ulong slot, fd_block_map_t * block_map_entry_out, fd_block_rewards_t * rewards_out, fd_hash_t * parent_block_hash_out, fd_valloc_t alloc, uchar ** block_data_out, ulong * block_data_out_sz );
537 :
538 : /* fd_blockstore_block_map_query_volatile is the same as above except it
539 : only copies out the metadata (fd_block_map_t). Returns
540 : FD_BLOCKSTORE_SLOT_MISSING if slot is missing, otherwise
541 : FD_BLOCKSTORE_OK. */
542 :
543 : int
544 : fd_blockstore_block_map_query_volatile( fd_blockstore_t * blockstore, ulong slot, fd_block_map_t * block_map_entry_out );
545 :
546 : /* Query the transaction data for the given signature */
547 : fd_blockstore_txn_map_t *
548 : fd_blockstore_txn_query( fd_blockstore_t * blockstore, uchar const sig[static FD_ED25519_SIG_SZ] );
549 :
550 : /* Query the transaction data for the given signature in a thread
551 : safe manner. The transaction data is copied out. txn_data_out can
552 : be NULL if you are only interested in the transaction metadata. */
553 : int
554 : fd_blockstore_txn_query_volatile( fd_blockstore_t * blockstore, uchar const sig[static FD_ED25519_SIG_SZ], fd_blockstore_txn_map_t * txn_out, long * blk_ts, uchar * blk_flags, uchar txn_data_out[FD_TXN_MTU] );
555 :
556 : /* Remove slot from blockstore, including all relevant internal structures. */
557 : void
558 : fd_blockstore_slot_remove( fd_blockstore_t * blockstore, ulong slot );
559 :
560 : /* Remove all the unassembled shreds for a slot */
561 : int
562 : fd_blockstore_buffered_shreds_remove( fd_blockstore_t * blockstore, ulong slot );
563 :
564 : /* Set the block height. */
565 : void
566 : fd_blockstore_block_height_update( fd_blockstore_t * blockstore, ulong slot, ulong block_height );
567 :
568 : /* fd_blockstore_publish publishes root to the blockstore, pruning any
569 : paths that are not in root's subtree. Removes all blocks in the
570 : pruned paths. Returns FD_BLOCKSTORE_OK on success,
571 : FD_BLOCKSTORE_ERR_X otherwise. Caller MUST hold the write lock. */
572 : int
573 : fd_blockstore_publish( fd_blockstore_t * blockstore, ulong root_slot );
574 :
575 : /* Acquire a read lock */
576 : static inline void
577 0 : fd_blockstore_start_read( fd_blockstore_t * blockstore ) {
578 0 : fd_rwseq_start_read( &blockstore->lock );
579 0 : }
580 :
581 : /* Release a read lock */
582 : static inline void
583 0 : fd_blockstore_end_read( fd_blockstore_t * blockstore ) {
584 0 : fd_rwseq_end_read( &blockstore->lock );
585 0 : }
586 :
587 : /* Acquire a write lock */
588 : static inline void
589 0 : fd_blockstore_start_write( fd_blockstore_t * blockstore ) {
590 0 : fd_rwseq_start_write( &blockstore->lock );
591 0 : }
592 :
593 : /* Release a write lock */
594 : static inline void
595 0 : fd_blockstore_end_write( fd_blockstore_t * blockstore ) {
596 0 : fd_rwseq_end_write( &blockstore->lock );
597 0 : }
598 :
599 : void
600 : fd_blockstore_log_block_status( fd_blockstore_t * blockstore, ulong around_slot );
601 :
602 : /* fd_blockstore_log_mem_usage logs the memory usage of blockstore in a
603 : human-readable format. Caller MUST hold the read lock. */
604 : void
605 : fd_blockstore_log_mem_usage( fd_blockstore_t * blockstore );
606 :
607 : FD_PROTOTYPES_END
608 :
609 : #endif /* HEADER_fd_src_flamenco_runtime_fd_blockstore_h */
|