@@ -6,7 +6,10 @@ use core::fmt;
6
6
use lambdaworks_math:: field:: {
7
7
element:: FieldElement , fields:: fft_friendly:: stark_252_prime_field:: Stark252PrimeField ,
8
8
} ;
9
- use serde:: { de, Deserialize , Serialize } ;
9
+ use serde:: {
10
+ de:: { self } ,
11
+ Deserialize , Serialize ,
12
+ } ;
10
13
11
14
use super :: Felt ;
12
15
@@ -18,7 +21,9 @@ impl Serialize for Felt {
18
21
if serializer. is_human_readable ( ) {
19
22
serializer. serialize_str ( & format ! ( "{:#x}" , self ) )
20
23
} 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..] )
22
27
}
23
28
}
24
29
}
@@ -66,21 +71,25 @@ impl de::Visitor<'_> for FeltVisitor {
66
71
where
67
72
E : de:: Error ,
68
73
{
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 ) ) ;
72
76
}
77
+
78
+ let mut buffer = [ 0u8 ; 32 ] ;
79
+ buffer[ 32 - value. len ( ) ..] . copy_from_slice ( value) ;
80
+ Ok ( Felt :: from_bytes_be ( & buffer) )
73
81
}
74
82
}
75
83
76
84
#[ cfg( test) ]
77
85
mod tests {
78
86
use super :: * ;
87
+ use bincode:: Options ;
88
+ use proptest:: prelude:: * ;
89
+ use serde_test:: { assert_tokens, Configure , Token } ;
79
90
80
91
#[ test]
81
92
fn serde ( ) {
82
- use serde_test:: { assert_tokens, Configure , Token } ;
83
-
84
93
assert_tokens ( & Felt :: ZERO . readable ( ) , & [ Token :: String ( "0x0" ) ] ) ;
85
94
assert_tokens ( & Felt :: TWO . readable ( ) , & [ Token :: String ( "0x2" ) ] ) ;
86
95
assert_tokens ( & Felt :: THREE . readable ( ) , & [ Token :: String ( "0x3" ) ] ) ;
@@ -91,21 +100,48 @@ mod tests {
91
100
) ] ,
92
101
) ;
93
102
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 ] ) ] ) ;
105
106
static MAX : [ u8 ; 32 ] = [
106
107
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 ,
107
108
0 , 0 , 0 ,
108
109
] ;
109
110
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
+ }
110
146
}
111
147
}
0 commit comments