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