@@ -6,7 +6,10 @@ use core::fmt;
66use lambdaworks_math:: field:: {
77 element:: FieldElement , fields:: fft_friendly:: stark_252_prime_field:: Stark252PrimeField ,
88} ;
9- use serde:: { de, Deserialize , Serialize } ;
9+ use serde:: {
10+ de:: { self } ,
11+ Deserialize , Serialize ,
12+ } ;
1013
1114use super :: Felt ;
1215
@@ -18,7 +21,9 @@ impl Serialize for Felt {
1821 if serializer. is_human_readable ( ) {
1922 serializer. serialize_str ( & format ! ( "{:#x}" , self ) )
2023 } else {
21- serializer. serialize_bytes ( & self . to_bytes_be ( ) )
24+ let be_bytes = self . to_bytes_be ( ) ;
25+ let first_significant_byte_index = be_bytes. iter ( ) . position ( |& b| b != 0 ) . unwrap_or ( 31 ) ;
26+ serializer. serialize_bytes ( & be_bytes[ first_significant_byte_index..] )
2227 }
2328 }
2429}
@@ -66,21 +71,25 @@ impl de::Visitor<'_> for FeltVisitor {
6671 where
6772 E : de:: Error ,
6873 {
69- match value. try_into ( ) {
70- Ok ( v) => Ok ( Felt :: from_bytes_be ( & v) ) ,
71- _ => Err ( de:: Error :: invalid_length ( value. len ( ) , & self ) ) ,
74+ if value. len ( ) > 32 {
75+ return Err ( de:: Error :: invalid_length ( value. len ( ) , & self ) ) ;
7276 }
77+
78+ let mut buffer = [ 0u8 ; 32 ] ;
79+ buffer[ 32 - value. len ( ) ..] . copy_from_slice ( value) ;
80+ Ok ( Felt :: from_bytes_be ( & buffer) )
7381 }
7482}
7583
7684#[ cfg( test) ]
7785mod tests {
7886 use super :: * ;
87+ use bincode:: Options ;
88+ use proptest:: prelude:: * ;
89+ use serde_test:: { assert_tokens, Configure , Token } ;
7990
8091 #[ test]
8192 fn serde ( ) {
82- use serde_test:: { assert_tokens, Configure , Token } ;
83-
8493 assert_tokens ( & Felt :: ZERO . readable ( ) , & [ Token :: String ( "0x0" ) ] ) ;
8594 assert_tokens ( & Felt :: TWO . readable ( ) , & [ Token :: String ( "0x2" ) ] ) ;
8695 assert_tokens ( & Felt :: THREE . readable ( ) , & [ Token :: String ( "0x3" ) ] ) ;
@@ -91,21 +100,48 @@ mod tests {
91100 ) ] ,
92101 ) ;
93102
94- assert_tokens ( & Felt :: ZERO . compact ( ) , & [ Token :: Bytes ( & [ 0 ; 32 ] ) ] ) ;
95- static TWO : [ u8 ; 32 ] = [
96- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
97- 0 , 0 , 2 ,
98- ] ;
99- assert_tokens ( & Felt :: TWO . compact ( ) , & [ Token :: Bytes ( & TWO ) ] ) ;
100- static THREE : [ u8 ; 32 ] = [
101- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
102- 0 , 0 , 3 ,
103- ] ;
104- assert_tokens ( & Felt :: THREE . compact ( ) , & [ Token :: Bytes ( & THREE ) ] ) ;
103+ assert_tokens ( & Felt :: ZERO . compact ( ) , & [ Token :: Bytes ( & [ 0 ; 1 ] ) ] ) ;
104+ assert_tokens ( & Felt :: TWO . compact ( ) , & [ Token :: Bytes ( & [ 2 ] ) ] ) ;
105+ assert_tokens ( & Felt :: THREE . compact ( ) , & [ Token :: Bytes ( & [ 3 ] ) ] ) ;
105106 static MAX : [ u8 ; 32 ] = [
106107 8 , 0 , 0 , 0 , 0 , 0 , 0 , 17 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
107108 0 , 0 , 0 ,
108109 ] ;
109110 assert_tokens ( & Felt :: MAX . compact ( ) , & [ Token :: Bytes ( & MAX ) ] ) ;
111+ assert_tokens (
112+ & Felt :: from_hex_unchecked ( "0xbabe" ) . compact ( ) ,
113+ & [ Token :: Bytes ( & [ 0xba , 0xbe ] ) ] ,
114+ ) ;
115+ assert_tokens (
116+ & Felt :: from_hex_unchecked ( "0xba000000be" ) . compact ( ) ,
117+ & [ Token :: Bytes ( & [ 0xba , 0 , 0 , 0 , 0xbe ] ) ] ,
118+ ) ;
119+ assert_tokens (
120+ & Felt :: from_hex_unchecked ( "0xbabe0000" ) . compact ( ) ,
121+ & [ Token :: Bytes ( & [ 0xba , 0xbe , 0 , 0 ] ) ] ,
122+ ) ;
123+ }
124+
125+ #[ test]
126+ fn backward_compatible_deserialization ( ) {
127+ static TWO_SERIALIZED_USING_PREVIOUS_IMPLEMENTATION : [ u8 ; 33 ] = [
128+ 32 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
129+ 0 , 0 , 0 , 2 ,
130+ ] ;
131+
132+ let options = bincode:: DefaultOptions :: new ( ) ;
133+ let deserialized = options
134+ . deserialize ( & TWO_SERIALIZED_USING_PREVIOUS_IMPLEMENTATION )
135+ . unwrap ( ) ;
136+ assert_eq ! ( Felt :: TWO , deserialized) ;
137+ }
138+
139+ proptest ! {
140+ #[ test]
141+ fn compact_round_trip( ref x in any:: <Felt >( ) ) {
142+ let serialized = bincode:: serialize( & x) . unwrap( ) ;
143+ let deserialized: Felt = bincode:: deserialize( & serialized) . unwrap( ) ;
144+ prop_assert_eq!( x, & deserialized) ;
145+ }
110146 }
111147}
0 commit comments