Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_snapshot_fd_snapshot_create_h 2 : #define HEADER_fd_src_flamenco_snapshot_fd_snapshot_create_h 3 : 4 : /* fd_snapshot_create.h provides APIs for creating a Agave-compatible 5 : snapshot from a slot execution context. */ 6 : 7 : #include "fd_snapshot_base.h" 8 : #include "../runtime/fd_runtime_init.h" 9 : #include "../runtime/fd_txncache.h" 10 : #include "../../util/archive/fd_tar.h" 11 : #include "../types/fd_types.h" 12 : 13 0 : #define FD_BLOCKHASH_QUEUE_SIZE (300UL) 14 0 : #define FD_TICKS_PER_SLOT (64UL) 15 : 16 0 : #define FD_SNAPSHOT_DIR_MAX (256UL) 17 0 : #define FD_SNAPSHOT_VERSION_FILE ("version") 18 0 : #define FD_SNAPSHOT_VERSION ("1.2.0") 19 0 : #define FD_SNAPSHOT_VERSION_LEN (5UL) 20 0 : #define FD_SNAPSHOT_STATUS_CACHE_FILE ("snapshots/status_cache") 21 : 22 : #define FD_SNAPSHOT_TMP_ARCHIVE (".tmp.tar") 23 : #define FD_SNAPSHOT_TMP_INCR_ARCHIVE (".tmp_inc.tar") 24 : #define FD_SNAPSHOT_TMP_FULL_ARCHIVE_ZSTD (".tmp.tar.zst") 25 : #define FD_SNAPSHOT_TMP_INCR_ARCHIVE_ZSTD (".tmp_inc.tar.zst") 26 : 27 : /* This is a relatively arbitrary constant. The max size of a snapshot append 28 : vec file is 16MiB but this value can cause problems in practice according 29 : to the Agave team. 30 : 31 : TODO: Figure out exactly what those problems are. */ 32 0 : #define FD_SNAPSHOT_APPEND_VEC_SZ_MAX (2UL * 1024UL * 1024UL * 1024UL) /* 2 MiB */ 33 : 34 : union fd_features; 35 : typedef union fd_features fd_features_t; 36 : 37 : FD_PROTOTYPES_BEGIN 38 : 39 : /* fd_snapshot_ctx_t holds various data structures needed for snapshot 40 : creation. It contains the snapshot slot, the snapshot directory, 41 : whether the snapshot is incremental, the tarball writer, the allocator, 42 : and holds the snapshot hash. 43 : 44 : FIXME: The snapshot service will currently not correctly free memory that is 45 : allocated unless a bump allocator like fd_scratch or fd_spad are used. */ 46 : 47 : struct fd_snapshot_ctx { 48 : 49 : /* These parameters are setup by the caller of the snapshot service. */ 50 : ulong slot; /* Slot for the snapshot. */ 51 : char const * out_dir; /* Output directory. */ 52 : fd_spad_t * spad; /* Bump allocator. */ 53 : 54 : /* The two data structures from the runtime referenced by the snapshot service. */ 55 : fd_funk_t * funk; /* Funk handle. */ 56 : fd_txncache_t * status_cache; /* Status cache handle. */ 57 : 58 : uchar is_incremental; /* If it is incremental, set the fields and pass in data from the previous full snapshot. */ 59 : ulong last_snap_slot; /* Full snapshot slot. */ 60 : ulong last_snap_capitalization; /* Full snapshot capitalization. */ 61 : fd_hash_t * last_snap_acc_hash; /* Full snapshot account hash. */ 62 : 63 : fd_tpool_t * tpool; 64 : 65 : /* We need two files to represent the snapshot file because can not directly 66 : stream out the compressed snapshot with the current implementation of the 67 : snapshot service. This is because we write back into the tar archive. 68 : So, we first write out a tar archive, then this is compressed into a 69 : second file. The tmp_fd is the file used to write the tar archive and 70 : the snapshot_fd is used to write out the compressed file. */ 71 : int tmp_fd; 72 : int snapshot_fd; 73 : 74 : /* This gets setup within the context and not by the user. */ 75 : fd_tar_writer_t * writer; /* Tar writer. */ 76 : fd_hash_t snap_hash; /* Snapshot hash. */ 77 : fd_hash_t acc_hash; /* Account hash. */ 78 : fd_slot_bank_t slot_bank; /* Obtained from funk. */ 79 : fd_epoch_bank_t epoch_bank; /* Obtained from funk. */ 80 : fd_acc_mgr_t * acc_mgr; /* Wrapper for funk. */ 81 : fd_features_t * features; 82 : }; 83 : typedef struct fd_snapshot_ctx fd_snapshot_ctx_t; 84 : 85 : /* TODO: These functions should be moved elsewhere to a more common file as 86 : these functions are used by the replay tile and the batch tile for more 87 : than just snapshot creation. 88 : 89 : fd_snapshot_create_populate_fseq, fd_snapshot_create_is_incremental, and 90 : fd_snapshot_create_get_slot are helpers used to pack and unpack the fseq 91 : used to indicate if a snapshot is ready to be created and if the snapshot 92 : shoudl be incremental. The other bytes represent the slot that the snapshot 93 : will be created for. The most significant 8 bits determine if the snapshot 94 : is incremental and the least significant 56 bits are reserved for the slot. 95 : 96 : These functions are used for snapshot creation in the full client. 97 : 98 : fd_batch_fseq_pack, fd_batch_fseq_is_snapshot, fd_batch_fseq_is_eah, 99 : fd_batch_fseq_is_incremental, and fd_batch_fseq_get_slot are helpers used 100 : by the replay tile and the batch tile to communicate what work the 101 : batch tile should do. At the moment of this writing, the batch tile can 102 : either calculate the epoch account hash or create a snapshot. 103 : 104 : The msb is used to determine if the batch tile should calculate the epoch 105 : account hash or produce a snapshot. The next msb is used to determine if 106 : the snapshot is incremental, this bit is ignored if the epoch account 107 : hash is being calculated. The remaining 62 bits are used to store the slot 108 : at which the snapshot/hash should be calculated for. */ 109 : 110 : static ulong FD_FN_UNUSED 111 0 : fd_batch_fseq_pack( ulong is_snapshot, ulong is_incremental, ulong smr ) { 112 0 : return ((is_snapshot & 0x1UL) << 63UL) | ((is_incremental & 0x1UL) << 62UL) | (smr & 0x3FFFFFFFFFFFFFFUL); 113 0 : } 114 : 115 : static ulong FD_FN_UNUSED 116 0 : fd_batch_fseq_is_snapshot( ulong fseq ) { 117 0 : return (fseq >> 63UL) & 0x1UL; 118 0 : } 119 : 120 : static ulong FD_FN_UNUSED 121 0 : fd_batch_fseq_is_eah( ulong fseq ) { 122 0 : return !((fseq >> 63UL) & 0x1UL); 123 0 : } 124 : 125 : static ulong FD_FN_UNUSED 126 0 : fd_batch_fseq_is_incremental( ulong fseq ) { 127 0 : return (fseq >> 62UL) & 0x1UL; 128 0 : } 129 : 130 : static ulong FD_FN_UNUSED 131 0 : fd_batch_fseq_get_slot( ulong fseq ) { 132 0 : return fseq & 0x3FFFFFFFFFFFFFFUL; 133 0 : } 134 : 135 : /* fd_snapshot_create_new_snapshot is responsible for creating the different 136 : structures used for snapshot generation and outputting them to a servable, 137 : compressed tarball. The main components of a Solana snapshot are as follows: 138 : 139 : 1. Version - This is a file that contains the version of the snapshot. 140 : 2. Manifest - The manifest contains data about the state of the network 141 : as well as the index of the append vecs. 142 : a. The bank. This is the equivalent of the firedancer slot/epoch context. 143 : This contains almost all of the state of the network that is not 144 : encapsulated in the accounts. 145 : b. Append vec index. This is a list of all of the append vecs that are 146 : used to store the accounts. This is a slot indexed file. 147 : c. The manifest also contains other relevant metadata including the 148 : account/snapshot hash. 149 : 3. Status cache - the status cache holds the transaction statuses for the 150 : last 300 rooted slots. This is a nested data structure which is indexed 151 : by blockhash. See fd_txncache.h for more details on the status cache. 152 : 4. Accounts directory - the accounts directory contains the state of all 153 : of the accounts and is a set of files described by <slot#.id#>. These 154 : are described by the append vec index in the manifest. 155 : 156 : The files are written out into a tar archive which is then zstd compressed. 157 : 158 : This can produce either a full snapshot or an incremental snapshot depending 159 : on the value of is_incremental. An incremental snapshot will contain all of 160 : the information described above, except it will only contain accounts that 161 : have been modified or deleted since the creation of the last incremental 162 : snapshot. */ 163 : 164 : void 165 : fd_snapshot_create_new_snapshot( fd_snapshot_ctx_t * snapshot_ctx, 166 : fd_hash_t * out_hash, 167 : ulong * out_capitalization ); 168 : 169 : FD_PROTOTYPES_END 170 : 171 : #endif /* HEADER_fd_src_flamenco_snapshot_fd_snapshot_create_h */