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 "../../funk/fd_funk_base.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_features_t * features; 81 : }; 82 : typedef struct fd_snapshot_ctx fd_snapshot_ctx_t; 83 : 84 : /* TODO: These functions should be moved elsewhere to a more common file as 85 : these functions are used by the replay tile and the batch tile for more 86 : than just snapshot creation. 87 : 88 : fd_snapshot_create_populate_fseq, fd_snapshot_create_is_incremental, and 89 : fd_snapshot_create_get_slot are helpers used to pack and unpack the fseq 90 : used to indicate if a snapshot is ready to be created and if the snapshot 91 : shoudl be incremental. The other bytes represent the slot that the snapshot 92 : will be created for. The most significant 8 bits determine if the snapshot 93 : is incremental and the least significant 56 bits are reserved for the slot. 94 : 95 : These functions are used for snapshot creation in the full client. 96 : 97 : fd_batch_fseq_pack, fd_batch_fseq_is_snapshot, fd_batch_fseq_is_eah, 98 : fd_batch_fseq_is_incremental, and fd_batch_fseq_get_slot are helpers used 99 : by the replay tile and the batch tile to communicate what work the 100 : batch tile should do. At the moment of this writing, the batch tile can 101 : either calculate the epoch account hash or create a snapshot. 102 : 103 : The msb is used to determine if the batch tile should calculate the epoch 104 : account hash or produce a snapshot. The next msb is used to determine if 105 : the snapshot is incremental, this bit is ignored if the epoch account 106 : hash is being calculated. The remaining 62 bits are used to store the slot 107 : at which the snapshot/hash should be calculated for. */ 108 : 109 : static ulong FD_FN_UNUSED 110 0 : fd_batch_fseq_pack( ulong is_snapshot, ulong is_incremental, ulong smr ) { 111 0 : return ((is_snapshot & 0x1UL) << 63UL) | ((is_incremental & 0x1UL) << 62UL) | (smr & 0x3FFFFFFFFFFFFFFUL); 112 0 : } 113 : 114 : static ulong FD_FN_UNUSED 115 0 : fd_batch_fseq_is_snapshot( ulong fseq ) { 116 0 : return (fseq >> 63UL) & 0x1UL; 117 0 : } 118 : 119 : static ulong FD_FN_UNUSED 120 0 : fd_batch_fseq_is_eah( ulong fseq ) { 121 0 : return !((fseq >> 63UL) & 0x1UL); 122 0 : } 123 : 124 : static ulong FD_FN_UNUSED 125 0 : fd_batch_fseq_is_incremental( ulong fseq ) { 126 0 : return (fseq >> 62UL) & 0x1UL; 127 0 : } 128 : 129 : static ulong FD_FN_UNUSED 130 0 : fd_batch_fseq_get_slot( ulong fseq ) { 131 0 : return fseq & 0x3FFFFFFFFFFFFFFUL; 132 0 : } 133 : 134 : /* fd_snapshot_create_new_snapshot is responsible for creating the different 135 : structures used for snapshot generation and outputting them to a servable, 136 : compressed tarball. The main components of a Solana snapshot are as follows: 137 : 138 : 1. Version - This is a file that contains the version of the snapshot. 139 : 2. Manifest - The manifest contains data about the state of the network 140 : as well as the index of the append vecs. 141 : a. The bank. This is the equivalent of the firedancer slot/epoch context. 142 : This contains almost all of the state of the network that is not 143 : encapsulated in the accounts. 144 : b. Append vec index. This is a list of all of the append vecs that are 145 : used to store the accounts. This is a slot indexed file. 146 : c. The manifest also contains other relevant metadata including the 147 : account/snapshot hash. 148 : 3. Status cache - the status cache holds the transaction statuses for the 149 : last 300 rooted slots. This is a nested data structure which is indexed 150 : by blockhash. See fd_txncache.h for more details on the status cache. 151 : 4. Accounts directory - the accounts directory contains the state of all 152 : of the accounts and is a set of files described by <slot#.id#>. These 153 : are described by the append vec index in the manifest. 154 : 155 : The files are written out into a tar archive which is then zstd compressed. 156 : 157 : This can produce either a full snapshot or an incremental snapshot depending 158 : on the value of is_incremental. An incremental snapshot will contain all of 159 : the information described above, except it will only contain accounts that 160 : have been modified or deleted since the creation of the last incremental 161 : snapshot. */ 162 : 163 : void 164 : fd_snapshot_create_new_snapshot( fd_snapshot_ctx_t * snapshot_ctx, 165 : fd_hash_t * out_hash, 166 : ulong * out_capitalization ); 167 : 168 : FD_PROTOTYPES_END 169 : 170 : #endif /* HEADER_fd_src_flamenco_snapshot_fd_snapshot_create_h */