Line data Source code
1 : #ifndef HEADER_fd_src_choreo_tower_fd_tower_serdes_h 2 : #define HEADER_fd_src_choreo_tower_fd_tower_serdes_h 3 : 4 : /* fd_tower_serdes.h provides APIs for serializing and deserializing 5 : vote accounts and instructions. */ 6 : 7 : #include "../fd_choreo_base.h" 8 : #include "../../ballet/txn/fd_txn.h" 9 : #include "../../flamenco/runtime/program/vote/fd_vote_codec.h" 10 : 11 : struct fd_tower_vote; 12 : typedef struct fd_tower_vote fd_tower_vote_t; 13 : 14 : /* FD_VOTE_IX_KIND_* give vote program instruction discriminants (first 15 : four bytes of instruction data). Older instruction types are ignored 16 : by tower. */ 17 : 18 : #define FD_VOTE_IX_KIND_TOWER_SYNC (14) 19 : #define FD_VOTE_IX_KIND_TOWER_SYNC_SWITCH (15) 20 : 21 : /* fd_compact_tower_sync_serde describes the serialization / 22 : deserialization schema of a CompactTowerSync vote instruction. There 23 : are various legacy instructions for vote transactions, but current 24 : mainnet votes are almost exclusively this instruction. */ 25 : 26 : struct fd_compact_tower_sync_serde { /* CompactTowerSync */ 27 : ulong root; /* u64 */ 28 : struct { 29 : ushort lockouts_cnt; /* ShortU16 */ 30 : struct { 31 : ulong offset; /* VarInt */ 32 : uchar confirmation_count; /* u8 */ 33 : } lockouts[31]; 34 : }; 35 : fd_hash_t hash; /* [u8; 32] */ 36 : struct { 37 : uchar timestamp_option; /* Option */ 38 : long timestamp; /* UnixTimestamp */ 39 : }; 40 : fd_hash_t block_id; /* [u8; 32] */ 41 : }; 42 : typedef struct fd_compact_tower_sync_serde fd_compact_tower_sync_serde_t; 43 : 44 : /* fd_compact_tower_sync_ser serializes fd_compact_tower_sync_serde_t 45 : into a buffer. Returns 0 on success, -1 if the lockouts_cnt is 46 : greater than FD_TOWER_VOTE_MAX or buf_max is too small to fit the 47 : serialized data. On success, sets *buf_sz to the number of bytes 48 : written if buf_sz is non-NULL. */ 49 : 50 : int 51 : fd_compact_tower_sync_ser( fd_compact_tower_sync_serde_t const * serde, 52 : uchar * buf, 53 : ulong buf_max, 54 : ulong * buf_sz ); 55 : 56 : /* fd_compact_tower_sync_de deserializes at most buf_sz of buf into 57 : fd_compact_tower_sync_serde_t. Designed to deserialize untrusted 58 : inputs (gossip / TPU vote txns). Assumes buf is at least of size 59 : buf_sz. Returns 0 on success, -1 on deserialization failure. Note: 60 : the return value only indicates whether the wire format was valid, 61 : not whether the resulting tower is semantically valid (e.g. slots 62 : and confirmations are monotonically increasing). Callers must 63 : validate the deserialized tower contents separately. */ 64 : 65 : int 66 : fd_compact_tower_sync_de( fd_compact_tower_sync_serde_t * serde, 67 : uchar const * buf, 68 : ulong buf_sz ); 69 : 70 : /* fd_compact_tower_sync_to_votes expands the lockout offsets into 71 : ascending votes (out holds FD_TOWER_VOTE_MAX), count and root, 72 : ULONG_MAX if none. Returns -1 for a repeated or descending slot, a 73 : bad confirmation count or a vote past the lockout of the vote below. */ 74 : 75 : int 76 : fd_compact_tower_sync_to_votes( fd_compact_tower_sync_serde_t const * serde, 77 : fd_tower_vote_t * out, 78 : ulong * out_cnt, 79 : ulong * out_root ); 80 : 81 : /* A buffer with capacity FD_VOTE_STATE_DATA_MAX can fit any valid vote 82 : account supported by tower (v2, v3, and v4). */ 83 : 84 : #define FD_VOTE_STATE_DATA_MAX (3762UL) 85 : 86 : /* FD_VOTE_ACC_V* give vote account/state versions. */ 87 : 88 0 : #define FD_VOTE_ACC_V2 (1) 89 0 : #define FD_VOTE_ACC_V3 (2) 90 0 : #define FD_VOTE_ACC_V4 (3) 91 : FD_STATIC_ASSERT( FD_VOTE_ACC_V2==fd_vote_state_versioned_enum_v1_14_11, FD_VOTE_ACC_V2 ); 92 : FD_STATIC_ASSERT( FD_VOTE_ACC_V3==fd_vote_state_versioned_enum_v3, FD_VOTE_ACC_V3 ); 93 : FD_STATIC_ASSERT( FD_VOTE_ACC_V4==fd_vote_state_versioned_enum_v4, FD_VOTE_ACC_V4 ); 94 : 95 : /* fd_vote_acc describes the layout of a vote state stored in a vote 96 : account. The vote_acc_{...} deserializers assume trusted input 97 : (account data written to by the vote program). These structs are 98 : used to support zero-copy access (direct casts) of byte arrays 99 : containing the vote account data. 100 : 101 : fd_vote_acc is versioned, and the serialized formats differ depending 102 : on this. They correspond to Agave's VoteState0_23_5, 103 : VoteState1_14_11 and VoteState structs. 104 : 105 : VoteStatev0_23_5 is deprecated and there are no longer vote accounts 106 : of that version on testnet / mainnet. VoteState1_14_11 corresponds 107 : to FD_VOTE_ACC_V2 and VoteState corresponds to FD_VOTE_ACC_V3. The 108 : only difference between the two is the votes in V3 contain an 109 : additional uchar field `latency`. 110 : 111 : The binary layout begins with metadata in the vote account, followed 112 : by the voter's votes (tower), and terminates with the root. */ 113 : 114 : struct __attribute__((packed)) fd_vote_acc_vote { 115 : uchar latency; 116 : ulong slot; 117 : uint conf; 118 : }; 119 : typedef struct fd_vote_acc_vote fd_vote_acc_vote_t; 120 : 121 : struct __attribute__((packed)) fd_vote_acc_vote_v2 { 122 : ulong slot; 123 : uint conf; 124 : }; 125 : typedef struct fd_vote_acc_vote_v2 fd_vote_acc_vote_v2_t; 126 : 127 : struct __attribute__((packed)) fd_vote_acc { 128 : uint kind; 129 : union __attribute__((packed)) { 130 : struct __attribute__((packed)) { 131 : fd_pubkey_t node_pubkey; 132 : fd_pubkey_t authorized_withdrawer; 133 : uchar commission; 134 : ulong votes_cnt; 135 : fd_vote_acc_vote_v2_t votes[31]; /* variable-length */ 136 : /* uchar root_option */ 137 : /* ulong root */ 138 : } v2; 139 : 140 : struct __attribute__((packed)) { 141 : fd_pubkey_t node_pubkey; 142 : fd_pubkey_t authorized_withdrawer; 143 : uchar commission; 144 : ulong votes_cnt; 145 : fd_vote_acc_vote_t votes[31]; /* variable-length */ 146 : /* uchar root_option */ 147 : /* ulong root */ 148 : } v3; 149 : 150 : struct __attribute__((packed)) { 151 : fd_pubkey_t node_pubkey; 152 : fd_pubkey_t authorized_withdrawer; 153 : fd_pubkey_t inflation_rewards_collector; 154 : fd_pubkey_t block_revenue_collector; 155 : ushort inflation_rewards_commission_bps; 156 : ushort block_revenue_commission_bps; 157 : ulong pending_delegator_rewards; 158 : uchar has_bls_pubkey_compressed; 159 : uchar bls_pubkey_compressed[48]; 160 : /* ulong votes_cnt; */ 161 : /* fd_vote_acc_vote_t votes[31]; */ 162 : /* uchar root_option */ 163 : /* ulong root */ 164 : } v4; 165 : }; 166 : }; 167 : typedef struct fd_vote_acc fd_vote_acc_t; 168 : 169 : /* fd_vote_acc_desc is a lightweight vote account descriptor for zero- 170 : copy inspection of a vote account. */ 171 : 172 : struct fd_vote_acc_desc { 173 : int kind; /* FD_VOTE_ACC_* */ 174 : ushort votes_off; /* offset to vote array */ 175 : uchar vote_cnt; /* number of votes (max FD_TOWER_VOTE_MAX) */ 176 : uchar vote_stride; /* byte stride between votes */ 177 : ulong root_slot; /* ULONG_MAX if not set */ 178 : }; 179 : typedef struct fd_vote_acc_desc fd_vote_acc_desc_t; 180 : 181 : FD_PROTOTYPES_BEGIN 182 : 183 : /* fd_vote_acc_desc recovers offsets to vote account bits given 184 : serialized data. Does minimal input validation. Initializes *desc 185 : and returns desc on success, or NULL on failure (invalid or 186 : unsupported vote account data). */ 187 : 188 : fd_vote_acc_desc_t * 189 : fd_vote_acc_desc( fd_vote_acc_desc_t * desc, 190 : uchar const * data, 191 : ulong data_sz ); 192 : 193 : /* fd_vote_acc_desc_vote returns a pointer to a vote in a serialized 194 : vote account. The return type depends on desc->kind: 195 : - FD_VOTE_ACC_V2 -> fd_vote_acc_vote_v2_t 196 : - FD_VOTE_ACC_V3 -> fd_vote_acc_vote_t 197 : - FD_VOTE_ACC_V4 -> fd_vote_acc_vote_t */ 198 : 199 : FD_FN_PURE static inline void const * 200 : fd_vote_acc_desc_vote( fd_vote_acc_desc_t const * desc, 201 : uchar const * data, 202 0 : ulong idx ) { 203 0 : return data + desc->votes_off + idx*desc->vote_stride; 204 0 : } 205 : 206 : /* fd_txn_parse_simple_vote optionally extracts the decoded tower sync 207 : from a vote transaction. */ 208 : 209 : int 210 : fd_txn_parse_simple_vote( fd_txn_t const * txn, 211 : uchar const * payload, 212 : fd_compact_tower_sync_serde_t * opt_tower_sync ); 213 : 214 : FD_PROTOTYPES_END 215 : 216 : #endif /* HEADER_fd_src_choreo_tower_fd_tower_serdes_h */