@@ -91,7 +91,7 @@ const SIZE_OF_COMMON_SHRED_HEADER: usize = 83;
91
91
const SIZE_OF_DATA_SHRED_HEADER : usize = 5 ;
92
92
const SIZE_OF_CODING_SHRED_HEADER : usize = 6 ;
93
93
const SIZE_OF_SIGNATURE : usize = 64 ;
94
- const SIZE_OF_SHRED_TYPE : usize = 1 ;
94
+ const SIZE_OF_SHRED_VARIANT : usize = 1 ;
95
95
const SIZE_OF_SHRED_SLOT : usize = 8 ;
96
96
const SIZE_OF_SHRED_INDEX : usize = 4 ;
97
97
pub const SIZE_OF_NONCE : usize = 4 ;
@@ -108,8 +108,8 @@ pub const SIZE_OF_DATA_SHRED_PAYLOAD: usize = PACKET_DATA_SIZE
108
108
const_assert_eq ! ( SHRED_DATA_OFFSET , 88 ) ;
109
109
const SHRED_DATA_OFFSET : usize = SIZE_OF_COMMON_SHRED_HEADER + SIZE_OF_DATA_SHRED_HEADER ;
110
110
111
- const OFFSET_OF_SHRED_TYPE : usize = SIZE_OF_SIGNATURE ;
112
- const OFFSET_OF_SHRED_SLOT : usize = SIZE_OF_SIGNATURE + SIZE_OF_SHRED_TYPE ;
111
+ const OFFSET_OF_SHRED_VARIANT : usize = SIZE_OF_SIGNATURE ;
112
+ const OFFSET_OF_SHRED_SLOT : usize = SIZE_OF_SIGNATURE + SIZE_OF_SHRED_VARIANT ;
113
113
const OFFSET_OF_SHRED_INDEX : usize = OFFSET_OF_SHRED_SLOT + SIZE_OF_SHRED_SLOT ;
114
114
const_assert_eq ! ( SHRED_PAYLOAD_SIZE , 1228 ) ;
115
115
const SHRED_PAYLOAD_SIZE : usize = PACKET_DATA_SIZE - SIZE_OF_NONCE ;
@@ -151,6 +151,8 @@ pub enum Error {
151
151
InvalidShredFlags ( u8 ) ,
152
152
#[ error( "Invalid shred type" ) ]
153
153
InvalidShredType ,
154
+ #[ error( "Invalid shred variant" ) ]
155
+ InvalidShredVariant ,
154
156
}
155
157
156
158
#[ repr( u8 ) ]
@@ -174,11 +176,18 @@ pub enum ShredType {
174
176
Code = 0b0101_1010 ,
175
177
}
176
178
179
+ #[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq , Deserialize , Serialize ) ]
180
+ #[ serde( into = "u8" , try_from = "u8" ) ]
181
+ enum ShredVariant {
182
+ LegacyCode ,
183
+ LegacyData ,
184
+ }
185
+
177
186
/// A common header that is present in data and code shred headers
178
187
#[ derive( Clone , Copy , Debug , PartialEq , Eq , Deserialize , Serialize ) ]
179
188
struct ShredCommonHeader {
180
189
signature : Signature ,
181
- shred_type : ShredType ,
190
+ shred_variant : ShredVariant ,
182
191
slot : Slot ,
183
192
index : u32 ,
184
193
version : u16 ,
@@ -317,9 +326,15 @@ impl Shred {
317
326
}
318
327
319
328
pub fn new_from_serialized_shred ( shred : Vec < u8 > ) -> Result < Self , Error > {
320
- Ok ( match layout:: get_shred_type ( & shred) ? {
321
- ShredType :: Code => Self :: from ( ShredCode :: from_payload ( shred) ?) ,
322
- ShredType :: Data => Self :: from ( ShredData :: from_payload ( shred) ?) ,
329
+ Ok ( match layout:: get_shred_variant ( & shred) ? {
330
+ ShredVariant :: LegacyCode => {
331
+ let shred = legacy:: ShredCode :: from_payload ( shred) ?;
332
+ Self :: from ( ShredCode :: from ( shred) )
333
+ }
334
+ ShredVariant :: LegacyData => {
335
+ let shred = legacy:: ShredData :: from_payload ( shred) ?;
336
+ Self :: from ( ShredData :: from ( shred) )
337
+ }
323
338
} )
324
339
}
325
340
@@ -438,7 +453,7 @@ impl Shred {
438
453
439
454
#[ inline]
440
455
pub fn shred_type ( & self ) -> ShredType {
441
- self . common_header ( ) . shred_type
456
+ ShredType :: from ( self . common_header ( ) . shred_variant )
442
457
}
443
458
444
459
pub fn is_data ( & self ) -> bool {
@@ -531,14 +546,17 @@ pub mod layout {
531
546
0 ..SIZE_OF_SIGNATURE
532
547
}
533
548
549
+ pub ( super ) fn get_shred_variant ( shred : & [ u8 ] ) -> Result < ShredVariant , Error > {
550
+ let shred_variant = match shred. get ( OFFSET_OF_SHRED_VARIANT ) {
551
+ None => return Err ( Error :: InvalidPayloadSize ( shred. len ( ) ) ) ,
552
+ Some ( shred_variant) => * shred_variant,
553
+ } ;
554
+ ShredVariant :: try_from ( shred_variant) . map_err ( |_| Error :: InvalidShredVariant )
555
+ }
556
+
534
557
pub ( super ) fn get_shred_type ( shred : & [ u8 ] ) -> Result < ShredType , Error > {
535
- match shred. get ( OFFSET_OF_SHRED_TYPE ) {
536
- None => Err ( Error :: InvalidPayloadSize ( shred. len ( ) ) ) ,
537
- Some ( shred_type) => match ShredType :: try_from ( * shred_type) {
538
- Err ( _) => Err ( Error :: InvalidShredType ) ,
539
- Ok ( shred_type) => Ok ( shred_type) ,
540
- } ,
541
- }
558
+ let shred_variant = get_shred_variant ( shred) ?;
559
+ Ok ( ShredType :: from ( shred_variant) )
542
560
}
543
561
544
562
pub fn get_slot ( shred : & [ u8 ] ) -> Option < Slot > {
@@ -585,6 +603,38 @@ impl From<ShredData> for Shred {
585
603
}
586
604
}
587
605
606
+ impl From < ShredVariant > for ShredType {
607
+ #[ inline]
608
+ fn from ( shred_variant : ShredVariant ) -> Self {
609
+ match shred_variant {
610
+ ShredVariant :: LegacyCode => ShredType :: Code ,
611
+ ShredVariant :: LegacyData => ShredType :: Data ,
612
+ }
613
+ }
614
+ }
615
+
616
+ impl From < ShredVariant > for u8 {
617
+ fn from ( shred_variant : ShredVariant ) -> u8 {
618
+ match shred_variant {
619
+ ShredVariant :: LegacyCode => u8:: from ( ShredType :: Code ) ,
620
+ ShredVariant :: LegacyData => u8:: from ( ShredType :: Data ) ,
621
+ }
622
+ }
623
+ }
624
+
625
+ impl TryFrom < u8 > for ShredVariant {
626
+ type Error = Error ;
627
+ fn try_from ( shred_variant : u8 ) -> Result < Self , Self :: Error > {
628
+ if shred_variant == u8:: from ( ShredType :: Code ) {
629
+ Ok ( ShredVariant :: LegacyCode )
630
+ } else if shred_variant == u8:: from ( ShredType :: Data ) {
631
+ Ok ( ShredVariant :: LegacyData )
632
+ } else {
633
+ Err ( Error :: InvalidShredVariant )
634
+ }
635
+ }
636
+ }
637
+
588
638
// Get slot, index, and type from a packet with partial deserialize
589
639
pub fn get_shred_slot_index_type (
590
640
packet : & Packet ,
@@ -704,7 +754,7 @@ mod tests {
704
754
fn test_shred_constants ( ) {
705
755
let common_header = ShredCommonHeader {
706
756
signature : Signature :: default ( ) ,
707
- shred_type : ShredType :: Code ,
757
+ shred_variant : ShredVariant :: LegacyCode ,
708
758
slot : Slot :: MAX ,
709
759
index : u32:: MAX ,
710
760
version : u16:: MAX ,
@@ -745,8 +795,8 @@ mod tests {
745
795
bincode:: serialized_size( & Signature :: default ( ) ) . unwrap( ) as usize
746
796
) ;
747
797
assert_eq ! (
748
- SIZE_OF_SHRED_TYPE ,
749
- bincode:: serialized_size( & ShredType :: Code ) . unwrap( ) as usize
798
+ SIZE_OF_SHRED_VARIANT ,
799
+ bincode:: serialized_size( & ShredVariant :: LegacyCode ) . unwrap( ) as usize
750
800
) ;
751
801
assert_eq ! (
752
802
SIZE_OF_SHRED_SLOT ,
@@ -814,7 +864,7 @@ mod tests {
814
864
assert_eq ! ( Some ( ( 1 , 3 , ShredType :: Data ) ) , ret) ;
815
865
assert_eq ! ( stats, ShredFetchStats :: default ( ) ) ;
816
866
817
- packet. meta . size = OFFSET_OF_SHRED_TYPE ;
867
+ packet. meta . size = OFFSET_OF_SHRED_VARIANT ;
818
868
assert_eq ! ( None , get_shred_slot_index_type( & packet, & mut stats) ) ;
819
869
assert_eq ! ( stats. index_overrun, 1 ) ;
820
870
@@ -878,7 +928,7 @@ mod tests {
878
928
200 , // version
879
929
) ;
880
930
shred. copy_to_packet ( & mut packet) ;
881
- packet. buffer_mut ( ) [ OFFSET_OF_SHRED_TYPE ] = u8:: MAX ;
931
+ packet. buffer_mut ( ) [ OFFSET_OF_SHRED_VARIANT ] = u8:: MAX ;
882
932
883
933
assert_eq ! ( None , get_shred_slot_index_type( & packet, & mut stats) ) ;
884
934
assert_eq ! ( 1 , stats. bad_shred_type) ;
@@ -894,6 +944,7 @@ mod tests {
894
944
assert_matches ! ( bincode:: deserialize:: <ShredType >( & [ 1u8 ] ) , Err ( _) ) ;
895
945
// data shred
896
946
assert_eq ! ( ShredType :: Data as u8 , 0b1010_0101 ) ;
947
+ assert_eq ! ( u8 :: from( ShredType :: Data ) , 0b1010_0101 ) ;
897
948
assert_eq ! ( ShredType :: try_from( 0b1010_0101 ) , Ok ( ShredType :: Data ) ) ;
898
949
let buf = bincode:: serialize ( & ShredType :: Data ) . unwrap ( ) ;
899
950
assert_eq ! ( buf, vec![ 0b1010_0101 ] ) ;
@@ -903,6 +954,7 @@ mod tests {
903
954
) ;
904
955
// coding shred
905
956
assert_eq ! ( ShredType :: Code as u8 , 0b0101_1010 ) ;
957
+ assert_eq ! ( u8 :: from( ShredType :: Code ) , 0b0101_1010 ) ;
906
958
assert_eq ! ( ShredType :: try_from( 0b0101_1010 ) , Ok ( ShredType :: Code ) ) ;
907
959
let buf = bincode:: serialize ( & ShredType :: Code ) . unwrap ( ) ;
908
960
assert_eq ! ( buf, vec![ 0b0101_1010 ] ) ;
@@ -912,6 +964,42 @@ mod tests {
912
964
) ;
913
965
}
914
966
967
+ #[ test]
968
+ fn test_shred_variant_compat ( ) {
969
+ assert_matches ! ( ShredVariant :: try_from( 0u8 ) , Err ( _) ) ;
970
+ assert_matches ! ( ShredVariant :: try_from( 1u8 ) , Err ( _) ) ;
971
+ assert_matches ! ( ShredVariant :: try_from( 0b0101_0000 ) , Err ( _) ) ;
972
+ assert_matches ! ( ShredVariant :: try_from( 0b1010_0000 ) , Err ( _) ) ;
973
+ assert_matches ! ( bincode:: deserialize:: <ShredVariant >( & [ 0b0101_0000 ] ) , Err ( _) ) ;
974
+ assert_matches ! ( bincode:: deserialize:: <ShredVariant >( & [ 0b1010_0000 ] ) , Err ( _) ) ;
975
+ // Legacy coding shred.
976
+ assert_eq ! ( u8 :: from( ShredVariant :: LegacyCode ) , 0b0101_1010 ) ;
977
+ assert_eq ! ( ShredType :: from( ShredVariant :: LegacyCode ) , ShredType :: Code ) ;
978
+ assert_matches ! (
979
+ ShredVariant :: try_from( 0b0101_1010 ) ,
980
+ Ok ( ShredVariant :: LegacyCode )
981
+ ) ;
982
+ let buf = bincode:: serialize ( & ShredVariant :: LegacyCode ) . unwrap ( ) ;
983
+ assert_eq ! ( buf, vec![ 0b0101_1010 ] ) ;
984
+ assert_matches ! (
985
+ bincode:: deserialize:: <ShredVariant >( & [ 0b0101_1010 ] ) ,
986
+ Ok ( ShredVariant :: LegacyCode )
987
+ ) ;
988
+ // Legacy data shred.
989
+ assert_eq ! ( u8 :: from( ShredVariant :: LegacyData ) , 0b1010_0101 ) ;
990
+ assert_eq ! ( ShredType :: from( ShredVariant :: LegacyData ) , ShredType :: Data ) ;
991
+ assert_matches ! (
992
+ ShredVariant :: try_from( 0b1010_0101 ) ,
993
+ Ok ( ShredVariant :: LegacyData )
994
+ ) ;
995
+ let buf = bincode:: serialize ( & ShredVariant :: LegacyData ) . unwrap ( ) ;
996
+ assert_eq ! ( buf, vec![ 0b1010_0101 ] ) ;
997
+ assert_matches ! (
998
+ bincode:: deserialize:: <ShredVariant >( & [ 0b1010_0101 ] ) ,
999
+ Ok ( ShredVariant :: LegacyData )
1000
+ ) ;
1001
+ }
1002
+
915
1003
#[ test]
916
1004
fn test_serde_compat_shred_data ( ) {
917
1005
const SEED : & str = "6qG9NGWEtoTugS4Zgs46u8zTccEJuRHtrNMiUayLHCxt" ;
0 commit comments