Line data Source code
1 : #ifndef HEADER_fd_src_ballet_shred_fd_shred_h
2 : #define HEADER_fd_src_ballet_shred_fd_shred_h
3 :
4 : #include "../bmtree/fd_bmtree.h"
5 :
6 : /* Shreds form the on-wire representation of Solana block data
7 : optimized for transmission over unreliable links/WAN.
8 :
9 : ### Layout
10 :
11 : Each shred is 1228 bytes long.
12 :
13 : +------------------------+
14 : | Common Shred Header | 83 bytes
15 : +------------------------+
16 : | Data Header | 5 bytes
17 : | or Coding Header | or 6 bytes
18 : +------------------------+
19 : | | variable
20 : | Payload | length
21 : | |
22 : +------------------------+
23 :
24 : for Merkle shreds, followed by:
25 :
26 : +------------------------+
27 : | (Chained merkle root) | 32 bytes
28 : +------------------------+
29 : +------------------------+
30 : | Merkle node #0 (root) | 20 bytes
31 : +------------------------+
32 : | Merkle node #1 | 20 bytes
33 : ..........................
34 :
35 : for resigned shreds, followed by:
36 :
37 : +------------------------+
38 : | signature | 64 bytes
39 : ..........................
40 :
41 : ### Shredding
42 :
43 : For a given input data blob (usually an entry batch),
44 : data shreds are derived by simply splitting up the blob into subslices.
45 :
46 : Each shred is sized such that it fits into a single UDP packet,
47 : i.e. currently bound by the generally accepted IPv6 MTU of 1280 bytes.
48 :
49 : ### Forward Error Correction
50 :
51 : Coding shreds implement Reed-Solomon error correction to provide tolerance against packet loss.
52 :
53 : Each data shred is first assigned an FEC set.
54 : For the vector of data shreds in each set, a corresponding vector of coding shreds contains parity data.
55 :
56 : FEC sets and entry batches do not necessarily align.
57 :
58 : ### Merkle Inclusion Proofs
59 :
60 : Data and coding shreds come in two variants respectively: legacy and merkle.
61 : Merkle shreds extend legacy shreds by adding FEC set inclusion proofs.
62 :
63 : It allows the block producer to commit to the vector of shreds that make up an FEC set.
64 : The inclusion proof is used to verify whether a shred is part of the FEC set commitment.
65 :
66 : The length of the inclusion proof is indicated by the variant field.
67 :
68 : ### resigned shreds
69 :
70 : Resigned shreds allow for an additional signature to be added on to lock down
71 : the retransmitter for turbine propagation
72 :
73 : ### Authentication
74 :
75 : Shreds are signed by the block producer.
76 : Consequentially, only the block producer is able to create valid shreds for any given block. */
77 :
78 : #include "../fd_ballet.h"
79 :
80 : /* FD_SHRED_MAX_SZ: The max byte size of a shred.
81 : This limit derives from the IPv6 MTU of 1280 bytes, minus 48 bytes
82 : for the UDP/IPv6 headers and another 4 bytes for good measure. Most
83 : shreds are this size, but Merkle data shreds may be smaller. */
84 208698579 : #define FD_SHRED_MAX_SZ (1228UL)
85 : /* FD_SHRED_MIN_SZ: The minimum byte size of a shred.
86 : A code shred of the max size covers a data shred of the minimum size
87 : with no padding. */
88 208696650 : #define FD_SHRED_MIN_SZ (1203UL)
89 : /* FD_SHRED_DATA_HEADER_SZ: size of all headers for data type shreds. */
90 104868267 : #define FD_SHRED_DATA_HEADER_SZ (0x58UL)
91 : /* FD_SHRED_CODE_HEADER_SZ: size of all headers for coding type shreds. */
92 55720704 : #define FD_SHRED_CODE_HEADER_SZ (0x59UL)
93 : /* This is a conservative bound.
94 : It's possible for a modified validator to create a data shred with
95 : this much payload.
96 : A validator that follows the default shredding policy should have
97 : payloads of no more than 1015 bytes.
98 : In general, shreds that are chained or resigned should have smaller
99 : payloads and a tigher bound. */
100 0 : #define FD_SHRED_DATA_PAYLOAD_MAX (FD_SHRED_MIN_SZ-FD_SHRED_DATA_HEADER_SZ)
101 :
102 : /* FD_SHRED_TYPE_* identifies the type of a shred.
103 : It is located at the four high bits of byte 0x40 (64) of the shred header
104 : and can be extracted using the fd_shred_type() function. */
105 : /* FD_SHRED_TYPE_LEGACY_DATA: A shred carrying raw binary data. */
106 140953794 : #define FD_SHRED_TYPE_LEGACY_DATA ((uchar)0xA0)
107 : /* FD_SHRED_TYPE_LEGACY_CODE: A shred carrying Reed-Solomon ECC. */
108 : #define FD_SHRED_TYPE_LEGACY_CODE ((uchar)0x50)
109 : /* FD_SHRED_TYPE_MERKLE_DATA: A shred carrying raw binary data and a merkle inclusion proof. */
110 1631202 : #define FD_SHRED_TYPE_MERKLE_DATA ((uchar)0x80)
111 : /* FD_SHRED_TYPE_MERKLE_CODE: A shred carrying Reed-Solomon ECC and a merkle inclusion proof. */
112 210678171 : #define FD_SHRED_TYPE_MERKLE_CODE ((uchar)0x40)
113 : /* FD_SHRED_TYPE_MERKLE_DATA_CHAINED: A shred carrying raw binary data and a chained merkle inclusion proof. */
114 40251312 : #define FD_SHRED_TYPE_MERKLE_DATA_CHAINED ((uchar)0x90)
115 : /* FD_SHRED_TYPE_MERKLE_CODE_CHAINED: A shred carrying Reed-Solomon ECC and a chained merkle inclusion proof. */
116 40250445 : #define FD_SHRED_TYPE_MERKLE_CODE_CHAINED ((uchar)0x60)
117 :
118 : /* FD_SHRED_TYPE_MERKLE_DATA_CHAINED_RESIGNED: A shred carrying raw binary data and a chained merkle inclusion proof and resigned. */
119 271975962 : #define FD_SHRED_TYPE_MERKLE_DATA_CHAINED_RESIGNED ((uchar)0xB0)
120 : /* FD_SHRED_TYPE_MERKLE_CODE_CHAINED_RESIGNED: A shred carrying Reed-Solomon ECC and a chained merkle inclusion proof and resigned. */
121 271974327 : #define FD_SHRED_TYPE_MERKLE_CODE_CHAINED_RESIGNED ((uchar)0x70)
122 :
123 : /* FD_SHRED_TYPEMASK_DATA: bitwise AND with type matches data shred */
124 : #define FD_SHRED_TYPEMASK_DATA FD_SHRED_TYPE_MERKLE_DATA
125 : /* FD_SHRED_TYPEMASK_CODE: bitwise AND with type matches code shred */
126 208654776 : #define FD_SHRED_TYPEMASK_CODE FD_SHRED_TYPE_MERKLE_CODE
127 :
128 : /* FD_SHRED_MERKLE_ROOT_SZ: the size of a merkle tree root in bytes. */
129 136389294 : #define FD_SHRED_MERKLE_ROOT_SZ (32UL)
130 : /* FD_SHRED_MERKLE_NODE_SZ: the size of a merkle inclusion proof node in bytes. */
131 175169571 : #define FD_SHRED_MERKLE_NODE_SZ (20UL)
132 : /* FD_SHRED_MERKLE_LAYER_CNT: the count of inclusion proof layers in the binary merkle tree. */
133 531 : #define FD_SHRED_MERKLE_LAYER_CNT (10UL)
134 : /* FD_SHRED_SIGNATURE_SZ: the size of a signature in a shred. */
135 211549560 : #define FD_SHRED_SIGNATURE_SZ (64UL)
136 : /* A merkle inclusion proof node. */
137 : typedef uchar fd_shred_merkle_t[FD_SHRED_MERKLE_NODE_SZ];
138 :
139 : FD_STATIC_ASSERT( sizeof(fd_bmtree_node_t) == FD_SHRED_MERKLE_ROOT_SZ, update FD_SHRED_MERKLE_ROOT_SZ );
140 :
141 : /* Constants relating to the data shred "flags" field. */
142 :
143 : /* Mask of the "reference tick" field in shred.data.flags */
144 0 : #define FD_SHRED_DATA_REF_TICK_MASK ((uchar)0x3f)
145 : /* Mask of the "slot complete" bit in shred.data.flags
146 : Indicates the last shred in a slot. */
147 0 : #define FD_SHRED_DATA_FLAG_SLOT_COMPLETE ((uchar)0x80)
148 : /* Mask of the "data batch complete" bit in shred.data.flags */
149 0 : #define FD_SHRED_DATA_FLAG_DATA_COMPLETE ((uchar)0x40)
150 :
151 : /* Maximum number of data shreds in a slot, also maximum number of parity shreds in a slot */
152 0 : #define FD_SHRED_BLK_MAX (1 << 15UL) /* 32,768 shreds */
153 : #define FD_SHRED_IDX_MAX (FD_SHRED_BLK_MAX - 1)
154 :
155 : /* Many static bounds are specified around the assumption that this is a
156 : protocol limit on the max number of shreds in a slot. If this limit
157 : changes, all the relevant usages in other areas of the Firedancer
158 : codebase should be updated before modifying this assertion. */
159 :
160 : FD_STATIC_ASSERT( FD_SHRED_BLK_MAX == 32768, check all usages before changing this limit! );
161 :
162 : /* Many static bounds are specified around the assumption that this is a
163 : protocol limit on the max number of shreds in a slot. If this limit
164 : changes, all the relevant usages in other areas of the Firedancer
165 : codebase should be updated before modifying this assertion. */
166 :
167 : FD_STATIC_ASSERT( FD_SHRED_BLK_MAX == 32768, check all usages before changing this limit! );
168 :
169 : /* 36,536,320 bytes per slot */
170 0 : #define FD_SHRED_DATA_PAYLOAD_MAX_PER_SLOT (FD_SHRED_DATA_PAYLOAD_MAX * FD_SHRED_BLK_MAX)
171 :
172 : /* 32,856 bytes per slot */
173 0 : #define FD_SHRED_DATA_HEADER_MAX_PER_SLOT (FD_SHRED_DATA_HEADER_SZ * FD_SHRED_BLK_MAX)
174 :
175 : /* Offset of the shred variant. Used for parsing. */
176 : #define FD_SHRED_VARIANT_OFF 0x40
177 :
178 : /* Firedancer-specific internal error codes.
179 :
180 : These are not part of the Solana protocol. */
181 :
182 0 : #define FD_SHRED_EBATCH 0x4000 /* End of batch reached (success)
183 : no more shreds and found FD_SHRED_DATA_FLAG_DATA_COMPLETE */
184 0 : #define FD_SHRED_ESLOT 0x8000 /* End of slot reached (success)
185 : no more shreds and found FD_SHRED_DATA_FLAG_SLOT_COMPLETE */
186 0 : #define FD_SHRED_ENOMEM 12 /* Error: Target buffer too small */
187 0 : #define FD_SHRED_EINVAL 22 /* Error: Invalid shred data */
188 0 : #define FD_SHRED_EPIPE 32 /* Error: Expected data in source buffer, got EOF */
189 :
190 : /* Primary shred data structure.
191 : Relies heavily on packed fields and unaligned memory accesses. */
192 : struct __attribute__((packed)) fd_shred {
193 : /* Ed25519 signature over the shred
194 :
195 : For legacy type shreds, signs over content of the shred structure past this signature field.
196 : For merkle type shreds, signs over the first node of the inclusion proof (merkle root). */
197 : /* 0x00 */ fd_ed25519_sig_t signature;
198 :
199 : /* Shred variant specifier
200 : Consists of two four bit fields. (Deliberately not using bit fields here)
201 :
202 : The high four bits indicate the shred type:
203 : - 0101: legacy code
204 : - 1010: legacy data
205 : - 0100: merkle code
206 : - 0110: merkle code (chained)
207 : - 0111: merkle code (chained resigned)
208 : - 1000: merkle data
209 : - 1001: merkle data (chained)
210 : - 1011: merkle data (chained resigned)
211 :
212 : For legacy type shreds, the low four bits are set to static patterns.
213 : For merkle type shreds, the low four bits are set to the number of non-root nodes in the inclusion proof.
214 : For merkle code type shreds, the 3rd highest bit represents if the merkle tree is chained.
215 : For merkle data type shreds, the 4th highest bit represents if the merkle tree is chained.
216 : For merkle code type shreds, the 4th highest bit represents if the shred is resigned.
217 : For merkle data type shreds, the 3th highest bit represents if the shred is resigned.
218 : */
219 : /* 0x40 */ uchar variant;
220 :
221 : /* Slot number that this shred is part of */
222 : /* 0x41 */ ulong slot;
223 :
224 : /* Index of this shred within the slot */
225 : /* 0x49 */ uint idx;
226 :
227 : /* Hash of the genesis version and historical hard forks of the current chain */
228 : /* 0x4d */ ushort version;
229 :
230 : /* Index into the vector of FEC sets for this slot. For data shreds, fec_set_idx<=idx. */
231 : /* 0x4f */ uint fec_set_idx;
232 :
233 : union {
234 : /* Common data shred header */
235 : struct __attribute__((packed)) {
236 : /* Slot number difference between this block and the parent block.
237 : parent_off <= slot.
238 : Always greater than zero, except for slot 0, in which case the
239 : previous invariant forces this to be 0. */
240 : /* 0x53 */ ushort parent_off;
241 :
242 : /* Bit field (MSB first)
243 : See FD_SHRED_DATA_FLAG_*
244 :
245 : [XX.. ....] Block complete? 0b00=no 0b01=no 0b11=yes (implies Entry batch complete)
246 : [.X.. ....] Entry batch complete? 0b0=no 0b1=yes
247 : [..XX XXXX] Reference tick number */
248 : /* 0x55 */ uchar flags;
249 :
250 : /* Shred size: size of data shred headers (88 bytes) + payload length */
251 : /* 0x56 */ ushort size;
252 : } data;
253 :
254 : /* Common coding shred header */
255 : struct __attribute__((packed)) {
256 : /* Total number of data shreds in FEC set. Must be positive <= FD_REEDSOL_DATA_SHREDS_MAX. */
257 : /* 0x53 */ ushort data_cnt;
258 :
259 : /* Total number of coding shreds in FEC set. Must be positive <= FD_REEDSOL_CODE_SHREDS_MAX. */
260 : /* 0x55 */ ushort code_cnt;
261 :
262 : /* Index within the vector of coding shreds in slot. In [0,
263 : code_cnt). Also, shred.code.idx <= shred.idx. */
264 : /* 0x57 */ ushort idx;
265 : } code;
266 : };
267 : };
268 : typedef struct fd_shred fd_shred_t;
269 :
270 : FD_PROTOTYPES_BEGIN
271 :
272 : /* fd_shred_parse: Parses and validates an untrusted shred stored in
273 : bytes buf[i] for i in [0, sz). sz must be at least FD_SHRED_MIN_SZ
274 : bytes. Allows trailing data.
275 :
276 : The returned pointer either equals the input pointer or is NULL if
277 : the given shred is malformed or violates any invariants described
278 : above. */
279 : FD_FN_PURE fd_shred_t const *
280 : fd_shred_parse( uchar const * buf,
281 : ulong sz );
282 :
283 : /* fd_shred_type: Returns the value of the shred's type field. (FD_SHRED_TYPE_*) */
284 : FD_FN_CONST static inline uchar
285 493020495 : fd_shred_type( uchar variant ) {
286 493020495 : return variant & 0xf0;
287 493020495 : }
288 :
289 : /* fd_shred_variant: Returns the encoded variant field
290 : given the shred type and merkle proof length. */
291 : FD_FN_CONST static inline uchar
292 : fd_shred_variant( uchar type,
293 106355181 : uchar merkle_cnt ) {
294 106355181 : if( FD_LIKELY( type==FD_SHRED_TYPE_LEGACY_DATA ) )
295 3 : merkle_cnt = 0x05;
296 106355181 : if( FD_LIKELY( type==FD_SHRED_TYPE_LEGACY_CODE ) )
297 3 : merkle_cnt = 0x0a;
298 106355181 : return (uchar)(type | merkle_cnt);
299 106355181 : }
300 :
301 : FD_FN_PURE static inline ulong
302 140937675 : fd_shred_sz( fd_shred_t const * shred ) {
303 140937675 : uchar type = fd_shred_type( shred->variant );
304 140937675 : return fd_ulong_if(
305 140937675 : type & FD_SHRED_TYPEMASK_CODE,
306 140937675 : FD_SHRED_MAX_SZ,
307 140937675 : fd_ulong_if( type==FD_SHRED_TYPE_LEGACY_DATA, shred->data.size, FD_SHRED_MIN_SZ)
308 140937675 : ); /* Legacy data */
309 140937675 : }
310 :
311 : /* fd_shred_header_sz: Returns the header size of a shred.
312 : Returns zero if the shred has an invalid variant.
313 :
314 : Accesses offsets up to FD_SHRED_HEADER_MIN_SZ. */
315 : FD_FN_CONST static inline ulong
316 33462 : fd_shred_header_sz( uchar variant ) {
317 33462 : uchar type = fd_shred_type( variant );
318 33462 : if( FD_LIKELY( type & FD_SHRED_TYPEMASK_DATA ) )
319 16266 : return FD_SHRED_DATA_HEADER_SZ;
320 17196 : if( FD_LIKELY( type & FD_SHRED_TYPEMASK_CODE ) )
321 17196 : return FD_SHRED_CODE_HEADER_SZ;
322 0 : return 0;
323 17196 : }
324 :
325 : /* fd_shred_merkle_cnt: Returns number of nodes in the merkle inclusion
326 : proof. Note that this excludes the root. Returns zero if the given
327 : shred is not a merkle variant. */
328 : FD_FN_CONST static inline uint
329 173756343 : fd_shred_merkle_cnt( uchar variant ) {
330 173756343 : uchar type = fd_shred_type( variant );
331 173756343 : if( FD_UNLIKELY( ( type == FD_SHRED_TYPE_LEGACY_DATA ) | ( type == FD_SHRED_TYPE_LEGACY_CODE ) ) )
332 45 : return 0;
333 173756298 : return (variant&0xfU);
334 173756343 : }
335 :
336 : /* fd_shred_merkle_sz: Returns the size in bytes of the merkle inclusion proof.
337 : Returns zero if the given shred is not a merkle variant. */
338 : FD_FN_CONST static inline ulong
339 173729163 : fd_shred_merkle_sz( uchar variant ) {
340 173729163 : return fd_shred_merkle_cnt( variant ) * FD_SHRED_MERKLE_NODE_SZ;
341 173729163 : }
342 :
343 :
344 : /* fd_shred_is_chained: Returns true if the shred is a chained merkle data or code shred. */
345 : FD_FN_CONST static inline uchar
346 38816274 : fd_shred_is_chained( ulong type ) {
347 38816274 : return (uchar)(
348 38816274 : ( type == FD_SHRED_TYPE_MERKLE_DATA_CHAINED )
349 38816274 : | ( type == FD_SHRED_TYPE_MERKLE_CODE_CHAINED )
350 38816274 : | ( type == FD_SHRED_TYPE_MERKLE_DATA_CHAINED_RESIGNED )
351 38816274 : | ( type == FD_SHRED_TYPE_MERKLE_CODE_CHAINED_RESIGNED ) );
352 38816274 : }
353 :
354 : /* fd_shred_is_resigned: Returns true if the shred is resigned by the retransmitter */
355 : FD_FN_CONST static inline uchar
356 231725562 : fd_shred_is_resigned( ulong type ) {
357 231725562 : return ( type == FD_SHRED_TYPE_MERKLE_DATA_CHAINED_RESIGNED )
358 231725562 : | ( type == FD_SHRED_TYPE_MERKLE_CODE_CHAINED_RESIGNED );
359 231725562 : }
360 :
361 : /* fd_shred_is_{data,code} return 1 if the provided shred type is one of
362 : the data (or code, respectively) types, and 0 if not. The value
363 : provided for type must be a valid shred type (one of the
364 : FD_SHRED_TYPE_* values). For the purposes of these functions,
365 : properties beyond data/code are ignored; e.g. a chained resigned
366 : Merkle data shred is considered a data shred. */
367 4516164 : FD_FN_CONST static inline uchar fd_shred_is_data( ulong type ) { return (type & 0xC0UL)==0x80UL; }
368 294 : FD_FN_CONST static inline uchar fd_shred_is_code( ulong type ) { return (type & 0xC0UL)==0x40UL; }
369 :
370 : /* fd_shred_swap_type: changes data into code or vice versa without
371 : affecting leagacy, merkle, chained, or resigned status. For example,
372 : fd_shred_swap_type( chained resigned data ) == chained resigned code.
373 : fd_shred_swap_type( merkle code ) == merkle data. */
374 : FD_FN_CONST static inline uchar
375 9372 : fd_shred_swap_type( ulong type ) {
376 : /* Swap bits 4 and 5. Swap bits 6 and 7. */
377 9372 : return (uchar)(((type & 0x50UL)<<1) | ((type&0xA0UL)>>1));
378 9372 : }
379 :
380 : /* fd_shred_payload_sz: Returns the payload size of a shred.
381 : Undefined behavior if the shred has not passed `fd_shred_parse`. */
382 : FD_FN_PURE static inline ulong
383 294 : fd_shred_payload_sz( fd_shred_t const * shred ) {
384 294 : ulong type = fd_shred_type( shred->variant );
385 294 : if( FD_LIKELY( type & FD_SHRED_TYPEMASK_DATA ) ) {
386 147 : return shred->data.size - FD_SHRED_DATA_HEADER_SZ;
387 147 : } else {
388 147 : return fd_shred_sz( shred ) - FD_SHRED_CODE_HEADER_SZ
389 147 : - fd_shred_merkle_sz( shred->variant )
390 147 : - fd_ulong_if( fd_shred_is_chained( type ), FD_SHRED_MERKLE_ROOT_SZ, 0 )
391 147 : - fd_ulong_if( fd_shred_is_resigned( type ), FD_SHRED_SIGNATURE_SZ, 0 );
392 147 : }
393 294 : }
394 :
395 : /* fd_shred_merkle_off: Returns the byte offset of the merkle inclusion proof of a shred.
396 :
397 : The provided shred must have passed validation in fd_shred_parse(). */
398 : FD_FN_PURE static inline ulong
399 105978453 : fd_shred_merkle_off( fd_shred_t const * shred ) {
400 105978453 : ulong type = fd_shred_type( shred->variant );
401 105978453 : return fd_shred_sz( shred )
402 105978453 : - fd_shred_merkle_sz( shred->variant )
403 105978453 : - fd_ulong_if( fd_shred_is_resigned( type ), FD_SHRED_SIGNATURE_SZ, 0 );
404 105978453 : }
405 :
406 : /* fd_shred_merkle_nodes: Returns a pointer to the shred's merkle proof data.
407 :
408 : The provided shred must have passed validation in fd_shred_parse(). */
409 : FD_FN_PURE static inline fd_shred_merkle_t const *
410 8931 : fd_shred_merkle_nodes( fd_shred_t const * shred ) {
411 8931 : uchar const * ptr = (uchar const *)shred;
412 8931 : ptr += fd_shred_merkle_off( shred );
413 8931 : return (fd_shred_merkle_t const *)ptr;
414 8931 : }
415 :
416 : /* fd_shred_merkle_root: Assuming that `shred` is a Merkle variant,
417 : reconstructs the merkle root from a shred and populates it in
418 : root_out. Returns 1 on success, 0 on failure. The output value must
419 : be ignored if a failure is returned. U.B. if the shred is not a
420 : merkle variant. */
421 : FD_FN_PURE int
422 : fd_shred_merkle_root( fd_shred_t const * shred, void * bmtree_mem, fd_bmtree_node_t * root_out );
423 :
424 : /* fd_shred_data_payload: Returns a pointer to a data shred payload.
425 :
426 : The provided shred must have passed validation in fd_shred_parse(),
427 : and must satisfy `type&FD_SHRED_TYPEMASK_DATA`
428 : where `uchar type = fd_shred_type( shred->variant )`. */
429 : FD_FN_CONST static inline uchar const *
430 9 : fd_shred_data_payload( fd_shred_t const * shred ) {
431 9 : return (uchar const *)shred + FD_SHRED_DATA_HEADER_SZ;
432 9 : }
433 :
434 : /* fd_shred_code_payload: Returns a pointer to a coding shred payload.
435 :
436 : The provided shred must have passed validation in fd_shred_parse(),
437 : and must satisfy `type&FD_SHRED_TYPEMASK_CODE`
438 : where `uchar type = fd_shred_type( shred->variant )`. */
439 : FD_FN_CONST static inline uchar const *
440 0 : fd_shred_code_payload( fd_shred_t const * shred ) {
441 0 : return (uchar const *)shred + FD_SHRED_CODE_HEADER_SZ;
442 0 : }
443 :
444 : /* fd_shred_chain_offset: Assuming that `shred` is a chained Merkle
445 : variant, compute the offset from the start of the shred to the start
446 : of the chained Merkle root. U.B. if the shred is not a chained
447 : variant. */
448 : FD_FN_CONST static inline ulong
449 67717101 : fd_shred_chain_off( uchar variant ) {
450 67717101 : ulong type = fd_shred_type( variant );
451 67717101 : return fd_ulong_if( type & FD_SHRED_TYPEMASK_CODE, FD_SHRED_MAX_SZ, FD_SHRED_MIN_SZ )
452 67717101 : - FD_SHRED_MERKLE_ROOT_SZ
453 67717101 : - fd_shred_merkle_sz( variant )
454 67717101 : - fd_ulong_if( fd_shred_is_resigned( type ), FD_SHRED_SIGNATURE_SZ, 0 );
455 67717101 : }
456 :
457 : /* fd_shred_retrasmitter_sig_off: Assuming that `shred` is a resigned
458 : variant, compute the offset from the start of the shred to the start
459 : of the retransmitter signature. U.B if the shred is not a resigned
460 : chained type. */
461 : FD_FN_PURE static inline ulong
462 34941159 : fd_shred_retransmitter_sig_off( fd_shred_t const * shred ) {
463 34941159 : return fd_shred_sz( shred )-FD_SHRED_SIGNATURE_SZ;
464 34941159 : }
465 :
466 : FD_PROTOTYPES_END
467 :
468 : #endif /* HEADER_fd_src_ballet_shred_fd_shred_h */
|