1- use serde:: { Deserialize , Deserializer , Serialize , de:: Visitor , ser:: SerializeTuple } ;
1+ use serde:: de:: { SeqAccess , Visitor } ;
2+ use serde:: { Deserialize , Serialize } ;
23use ssz:: { Decode , DecodeError , Encode } ;
34use std:: ops:: { Deref , DerefMut } ;
45
@@ -94,9 +95,10 @@ impl<const N: usize> Serialize for FieldArray<N> {
9495 where
9596 S : serde:: Serializer ,
9697 {
98+ use serde:: ser:: SerializeTuple ;
9799 let mut seq = serializer. serialize_tuple ( N ) ?;
98- for element in self . 0 . iter ( ) . map ( PrimeField32 :: as_canonical_u32 ) {
99- seq. serialize_element ( & element) ?;
100+ for element in & self . 0 {
101+ seq. serialize_element ( element) ?;
100102 }
101103 seq. end ( )
102104 }
@@ -105,7 +107,7 @@ impl<const N: usize> Serialize for FieldArray<N> {
105107impl < ' de , const N : usize > Deserialize < ' de > for FieldArray < N > {
106108 fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
107109 where
108- D : Deserializer < ' de > ,
110+ D : serde :: Deserializer < ' de > ,
109111 {
110112 struct FieldArrayVisitor < const N : usize > ;
111113
@@ -118,14 +120,13 @@ impl<'de, const N: usize> Deserialize<'de> for FieldArray<N> {
118120
119121 fn visit_seq < A > ( self , mut seq : A ) -> Result < Self :: Value , A :: Error >
120122 where
121- A : serde :: de :: SeqAccess < ' de > ,
123+ A : SeqAccess < ' de > ,
122124 {
123125 let mut arr = [ F :: ZERO ; N ] ;
124- for ( i, p ) in arr. iter_mut ( ) . enumerate ( ) {
125- let val : u32 = seq
126+ for ( i, elem ) in arr. iter_mut ( ) . enumerate ( ) {
127+ * elem = seq
126128 . next_element ( ) ?
127129 . ok_or_else ( || serde:: de:: Error :: invalid_length ( i, & self ) ) ?;
128- * p = F :: new ( val) ;
129130 }
130131 Ok ( FieldArray ( arr) )
131132 }
@@ -347,6 +348,41 @@ mod tests {
347348 prop_assert_eq!( encoded. len( ) , expected_size) ;
348349 prop_assert_eq!( field_array. ssz_bytes_len( ) , expected_size) ;
349350 }
351+
352+ #[ test]
353+ fn proptest_serde_roundtrip(
354+ values in prop:: collection:: vec( 0u32 ..F :: ORDER_U32 , LARGE_SIZE )
355+ ) {
356+ let arr: [ F ; LARGE_SIZE ] = std:: array:: from_fn( |i| F :: new( values[ i] ) ) ;
357+ let original = FieldArray ( arr) ;
358+
359+ let config = bincode:: config:: standard( ) . with_fixed_int_encoding( ) ;
360+ let encoded = bincode:: serde:: encode_to_vec( original, config)
361+ . expect( "Failed to serialize" ) ;
362+ let decoded: FieldArray <LARGE_SIZE > = bincode:: serde:: decode_from_slice( & encoded, config)
363+ . expect( "Failed to deserialize" )
364+ . 0 ;
365+
366+ prop_assert_eq!( original, decoded) ;
367+ }
368+
369+ #[ test]
370+ fn proptest_serde_deterministic(
371+ values in prop:: array:: uniform5( 0u32 ..F :: ORDER_U32 )
372+ ) {
373+ let arr = values. map( F :: new) ;
374+ let field_array = FieldArray ( arr) ;
375+
376+ let config = bincode:: config:: standard( ) . with_fixed_int_encoding( ) ;
377+
378+ // Encode twice and verify both encodings are identical
379+ let encoding1 = bincode:: serde:: encode_to_vec( field_array, config)
380+ . expect( "Failed to serialize" ) ;
381+ let encoding2 = bincode:: serde:: encode_to_vec( field_array, config)
382+ . expect( "Failed to serialize" ) ;
383+
384+ prop_assert_eq!( encoding1, encoding2) ;
385+ }
350386 }
351387
352388 #[ test]
@@ -370,4 +406,59 @@ mod tests {
370406 let encoded = bincode:: serde:: encode_to_vec ( arr, config) . unwrap ( ) ;
371407 assert_eq ! ( encoded. len( ) , arr. len( ) * F :: NUM_BYTES ) ;
372408 }
409+
410+ #[ test]
411+ fn test_serde_uses_montgomery_form ( ) {
412+ // Create a field array with known values
413+ let arr = FieldArray ( [ F :: new ( 1 ) , F :: new ( 2 ) , F :: new ( 3 ) ] ) ;
414+
415+ // Serialize using bincode
416+ let config = bincode:: config:: standard ( ) . with_fixed_int_encoding ( ) ;
417+ let encoded = bincode:: serde:: encode_to_vec ( arr, config) . unwrap ( ) ;
418+
419+ // Extract the raw u32 values from the encoded bytes
420+ let mut raw_values = Vec :: new ( ) ;
421+ for i in 0 ..arr. len ( ) {
422+ let start = i * F :: NUM_BYTES ;
423+ let chunk = & encoded[ start..start + F :: NUM_BYTES ] ;
424+ let value = u32:: from_le_bytes ( chunk. try_into ( ) . unwrap ( ) ) ;
425+ raw_values. push ( value) ;
426+ }
427+
428+ // Verify that the serialized values are in Montgomery form, not canonical form.
429+ //
430+ // - If they were in canonical form, we would see [1, 2, 3]
431+ // - In Montgomery form, they should be different values
432+ //
433+ // We check this to confirm the serialization is using Montgomery form as in Plonky3.
434+ //
435+ // This is for consistency with other serializations including field elements over the codebase.
436+ assert_ne ! (
437+ raw_values,
438+ vec![ 1 , 2 , 3 ] ,
439+ "Values should be in Montgomery form, not canonical form"
440+ ) ;
441+
442+ // Verify that when we access the internal value directly, it matches what was serialized
443+ // This confirms we're serializing the Montgomery representation
444+ for ( i, & expected_monty) in raw_values. iter ( ) . enumerate ( ) {
445+ // Access the internal Montgomery value through unsafe (for testing only)
446+ let actual_monty = unsafe {
447+ // SAFETY: MontyField31 is repr(transparent) with a u32 value field
448+ std:: ptr:: read ( ( & raw const arr[ i] ) . cast :: < u32 > ( ) )
449+ } ;
450+
451+ assert_eq ! (
452+ actual_monty, expected_monty,
453+ "Element {} should serialize its internal Montgomery form" ,
454+ i
455+ ) ;
456+ }
457+
458+ // Verify roundtrip works correctly
459+ let decoded: FieldArray < 3 > = bincode:: serde:: decode_from_slice ( & encoded, config)
460+ . expect ( "Failed to deserialize" )
461+ . 0 ;
462+ assert_eq ! ( arr, decoded, "Roundtrip should preserve values" ) ;
463+ }
373464}
0 commit comments