From 38353e3d3a89a4842b6a50129f30b094df1dad9e Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Tue, 2 Apr 2024 12:08:41 +1100 Subject: [PATCH 01/11] Add serde for BoxedUInt --- src/uint/boxed.rs | 58 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index ac698f5ab..3435a7cf5 100644 --- a/src/uint/boxed.rs +++ b/src/uint/boxed.rs @@ -33,6 +33,9 @@ use alloc::{boxed::Box, vec, vec::Vec}; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; +#[cfg(feature = "serde")] +use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer}; + #[cfg(feature = "zeroize")] use zeroize::Zeroize; @@ -395,12 +398,45 @@ impl fmt::UpperHex for BoxedUint { } } +#[cfg(feature = "serde")] +impl<'de, const LIMBS: usize> Deserialize<'de> for Uint +where + Uint: Encoding, +{ + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let mut buffer = Self::ZERO.to_le_bytes(); + serdect::array::deserialize_hex_or_bin(buffer.as_mut(), deserializer)?; + + Ok(Self::from_le_bytes(buffer)) + } +} + +#[cfg(feature = "serde")] +impl Serialize for Uint +where + Uint: Encoding, +{ + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serdect::array::serialize_hex_lower_or_bin(&Encoding::to_le_bytes(self), serializer) + } +} + #[cfg(test)] mod tests { use super::BoxedUint; use crate::Word; use alloc::vec::Vec; + /* TODO: U64 but for BoxedUInt ? */ + #[cfg(feature = "serde")] + use crate::U64; + #[test] fn from_word_vec() { let words: &[Word] = &[0, 1, 2, 3]; @@ -408,4 +444,26 @@ mod tests { assert_eq!(uint.nlimbs(), 4); assert_eq!(uint.as_words(), words); } + + #[cfg(feature = "serde")] + #[test] + fn serde() { + const TEST: U64 = U64::from_u64(0x0011223344556677); + + let serialized = bincode::serialize(&TEST).unwrap(); + let deserialized: U64 = bincode::deserialize(&serialized).unwrap(); + + assert_eq!(TEST, deserialized); + } + + #[cfg(feature = "serde")] + #[test] + fn serde_owned() { + const TEST: U64 = U64::from_u64(0x0011223344556677); + + let serialized = bincode::serialize(&TEST).unwrap(); + let deserialized: U64 = bincode::deserialize_from(serialized.as_slice()).unwrap(); + + assert_eq!(TEST, deserialized); + } } From fde0c078e7bf3d4263363043dd0e03d08d91ebd7 Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Tue, 2 Apr 2024 12:16:29 +1100 Subject: [PATCH 02/11] Plumb the right type for impl --- src/uint/boxed.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index 3435a7cf5..93f99eda2 100644 --- a/src/uint/boxed.rs +++ b/src/uint/boxed.rs @@ -28,7 +28,7 @@ mod sub_mod; #[cfg(feature = "rand_core")] mod rand; -use crate::{modular::BoxedMontyForm, Integer, Limb, NonZero, Odd, Word, Zero}; +use crate::{modular::BoxedMontyForm, Encoding, Integer, Limb, NonZero, Odd, Word, Zero}; use alloc::{boxed::Box, vec, vec::Vec}; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; @@ -399,9 +399,9 @@ impl fmt::UpperHex for BoxedUint { } #[cfg(feature = "serde")] -impl<'de, const LIMBS: usize> Deserialize<'de> for Uint +impl<'de> Deserialize<'de> for BoxedUint where - Uint: Encoding, + BoxedUint: Encoding, { fn deserialize(deserializer: D) -> Result where @@ -415,9 +415,9 @@ where } #[cfg(feature = "serde")] -impl Serialize for Uint +impl Serialize for BoxedUint where - Uint: Encoding, + BoxedUint: Encoding, { fn serialize(&self, serializer: S) -> Result where From 2a8b746f19c561d42b5e1d8eb109fee14551d7a8 Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Tue, 2 Apr 2024 12:18:21 +1100 Subject: [PATCH 03/11] Right encoding I think ? --- src/uint/boxed.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index 93f99eda2..a518879ca 100644 --- a/src/uint/boxed.rs +++ b/src/uint/boxed.rs @@ -28,7 +28,8 @@ mod sub_mod; #[cfg(feature = "rand_core")] mod rand; -use crate::{modular::BoxedMontyForm, Encoding, Integer, Limb, NonZero, Odd, Word, Zero}; +use crate::{modular::BoxedMontyForm, Integer, Limb, NonZero, Odd, Word, Zero}; +use encoding::Encoding; use alloc::{boxed::Box, vec, vec::Vec}; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; From 6abfd8e9a1d710683d2f63ab4f5c56e0d58c116a Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Tue, 2 Apr 2024 12:47:35 +1100 Subject: [PATCH 04/11] Plumb something maybe right --- src/uint/boxed.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index a518879ca..6d8be75d6 100644 --- a/src/uint/boxed.rs +++ b/src/uint/boxed.rs @@ -29,7 +29,6 @@ mod sub_mod; mod rand; use crate::{modular::BoxedMontyForm, Integer, Limb, NonZero, Odd, Word, Zero}; -use encoding::Encoding; use alloc::{boxed::Box, vec, vec::Vec}; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; @@ -401,30 +400,33 @@ impl fmt::UpperHex for BoxedUint { #[cfg(feature = "serde")] impl<'de> Deserialize<'de> for BoxedUint -where - BoxedUint: Encoding, +// TODO +//where +// BoxedUint: Encoding, { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { - let mut buffer = Self::ZERO.to_le_bytes(); + let mut buffer = Self::zero().to_le_bytes(); serdect::array::deserialize_hex_or_bin(buffer.as_mut(), deserializer)?; - Ok(Self::from_le_bytes(buffer)) + // TODO what precision ? /? TODO this is fallible - form_le_slice + Ok(Self::from_le_slice(&buffer, 0) + .expect("TODO: What should we do with fallible impl here")) } } #[cfg(feature = "serde")] impl Serialize for BoxedUint -where - BoxedUint: Encoding, +//where +// BoxedUint: Encoding, { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - serdect::array::serialize_hex_lower_or_bin(&Encoding::to_le_bytes(self), serializer) + serdect::array::serialize_hex_lower_or_bin(&self.to_le_bytes(), serializer) } } From 7f17c5a2d76cc966b27cf893698c28f8a536b3e8 Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Sat, 6 Apr 2024 15:25:39 +1100 Subject: [PATCH 05/11] Move under encoding and address other things --- src/uint/boxed/encoding/serde.rs | 63 ++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 src/uint/boxed/encoding/serde.rs diff --git a/src/uint/boxed/encoding/serde.rs b/src/uint/boxed/encoding/serde.rs new file mode 100644 index 000000000..328f57eb7 --- /dev/null +++ b/src/uint/boxed/encoding/serde.rs @@ -0,0 +1,63 @@ +//! Support for serdect encoding/decoding [`BoxedUint`] + +use serdect::serde::{de, Deserialize, Deserializer, Serialize, Serializer}; + +use crate::BoxedUint; + +impl<'de> Deserialize<'de> for BoxedUint { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let mut buffer = Self::zero().to_le_bytes(); + serdect::array::deserialize_hex_or_bin(buffer.as_mut(), deserializer)?; + + let bits_in = buffer.len() * 8; + + if bits_in > u32::MAX as usize { + return Err(de::Error::custom( + "Deserialize input overflows BoxedUint u32 bits length", + )); + } + + Self::from_le_slice(&buffer, bits_in as u32) + .map_err(|_| de::Error::custom("Deserialize error")) + } +} + +#[cfg(feature = "serde")] +impl Serialize for BoxedUint { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serdect::array::serialize_hex_lower_or_bin(&self.to_le_bytes(), serializer) + } +} + +#[cfg(test)] +mod tests { + use super::BoxedUint; + + #[test] + fn serde() { + #[allow(trivial_numeric_casts)] + let test: BoxedUint = BoxedUint::from(0x0011223344556677 as u64); + + let serialized = bincode::serialize(&test).unwrap(); + let deserialized: BoxedUint = bincode::deserialize(&serialized).unwrap(); + + assert_eq!(test, deserialized); + } + + #[test] + fn serde_owned() { + #[allow(trivial_numeric_casts)] + let test: BoxedUint = BoxedUint::from(0x0011223344556677 as u64); + + let serialized = bincode::serialize(&test).unwrap(); + let deserialized: BoxedUint = bincode::deserialize_from(serialized.as_slice()).unwrap(); + + assert_eq!(test, deserialized); + } +} From 628bc5edf4463fc4f0d43110dd0c158321975a6f Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Sat, 6 Apr 2024 15:27:24 +1100 Subject: [PATCH 06/11] Re-plumb serde --- src/uint/boxed.rs | 61 -------------------------------------- src/uint/boxed/encoding.rs | 9 ++++-- 2 files changed, 7 insertions(+), 63 deletions(-) diff --git a/src/uint/boxed.rs b/src/uint/boxed.rs index 6d8be75d6..ac698f5ab 100644 --- a/src/uint/boxed.rs +++ b/src/uint/boxed.rs @@ -33,9 +33,6 @@ use alloc::{boxed::Box, vec, vec::Vec}; use core::fmt; use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption}; -#[cfg(feature = "serde")] -use serdect::serde::{Deserialize, Deserializer, Serialize, Serializer}; - #[cfg(feature = "zeroize")] use zeroize::Zeroize; @@ -398,48 +395,12 @@ impl fmt::UpperHex for BoxedUint { } } -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for BoxedUint -// TODO -//where -// BoxedUint: Encoding, -{ - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let mut buffer = Self::zero().to_le_bytes(); - serdect::array::deserialize_hex_or_bin(buffer.as_mut(), deserializer)?; - - // TODO what precision ? /? TODO this is fallible - form_le_slice - Ok(Self::from_le_slice(&buffer, 0) - .expect("TODO: What should we do with fallible impl here")) - } -} - -#[cfg(feature = "serde")] -impl Serialize for BoxedUint -//where -// BoxedUint: Encoding, -{ - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serdect::array::serialize_hex_lower_or_bin(&self.to_le_bytes(), serializer) - } -} - #[cfg(test)] mod tests { use super::BoxedUint; use crate::Word; use alloc::vec::Vec; - /* TODO: U64 but for BoxedUInt ? */ - #[cfg(feature = "serde")] - use crate::U64; - #[test] fn from_word_vec() { let words: &[Word] = &[0, 1, 2, 3]; @@ -447,26 +408,4 @@ mod tests { assert_eq!(uint.nlimbs(), 4); assert_eq!(uint.as_words(), words); } - - #[cfg(feature = "serde")] - #[test] - fn serde() { - const TEST: U64 = U64::from_u64(0x0011223344556677); - - let serialized = bincode::serialize(&TEST).unwrap(); - let deserialized: U64 = bincode::deserialize(&serialized).unwrap(); - - assert_eq!(TEST, deserialized); - } - - #[cfg(feature = "serde")] - #[test] - fn serde_owned() { - const TEST: U64 = U64::from_u64(0x0011223344556677); - - let serialized = bincode::serialize(&TEST).unwrap(); - let deserialized: U64 = bincode::deserialize_from(serialized.as_slice()).unwrap(); - - assert_eq!(TEST, deserialized); - } } diff --git a/src/uint/boxed/encoding.rs b/src/uint/boxed/encoding.rs index 1baae6adf..7879914b0 100644 --- a/src/uint/boxed/encoding.rs +++ b/src/uint/boxed/encoding.rs @@ -1,5 +1,8 @@ //! Const-friendly decoding operations for [`BoxedUint`]. +#[cfg(feature = "serde")] +mod serde; + use super::BoxedUint; use crate::{uint::encoding, Limb, Word}; use alloc::boxed::Box; @@ -138,8 +141,9 @@ impl BoxedUint { let nlimbs = (bits_precision / Limb::BITS) as usize; let bytes = hex.as_bytes(); - assert!( - bytes.len() == Limb::BYTES * nlimbs * 2, + assert_eq!( + bytes.len(), + (Limb::BYTES * nlimbs * 2), "hex string is not the expected size" ); @@ -161,6 +165,7 @@ impl BoxedUint { res[nlimbs - i - 1] = Limb(Word::from_be_bytes(buf)); i += 1; } + CtOption::new(Self { limbs: res.into() }, Choice::from((err == 0) as u8)) } } From c6b7317c6e3715806953e9a7b05abf63e5d9c99e Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Sat, 6 Apr 2024 15:32:12 +1100 Subject: [PATCH 07/11] Unroll unrelated debug noise --- src/uint/boxed/encoding.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/uint/boxed/encoding.rs b/src/uint/boxed/encoding.rs index 7879914b0..1f83f7240 100644 --- a/src/uint/boxed/encoding.rs +++ b/src/uint/boxed/encoding.rs @@ -141,9 +141,8 @@ impl BoxedUint { let nlimbs = (bits_precision / Limb::BITS) as usize; let bytes = hex.as_bytes(); - assert_eq!( - bytes.len(), - (Limb::BYTES * nlimbs * 2), + assert!( + bytes.len() == Limb::BYTES * nlimbs * 2, "hex string is not the expected size" ); @@ -165,7 +164,6 @@ impl BoxedUint { res[nlimbs - i - 1] = Limb(Word::from_be_bytes(buf)); i += 1; } - CtOption::new(Self { limbs: res.into() }, Choice::from((err == 0) as u8)) } } From 8c58724bed4125024f7313e09886307a45f9f34a Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Sat, 6 Apr 2024 15:33:47 +1100 Subject: [PATCH 08/11] Documentation nit --- src/uint/boxed/encoding/serde.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uint/boxed/encoding/serde.rs b/src/uint/boxed/encoding/serde.rs index 328f57eb7..8656ecd96 100644 --- a/src/uint/boxed/encoding/serde.rs +++ b/src/uint/boxed/encoding/serde.rs @@ -1,4 +1,4 @@ -//! Support for serdect encoding/decoding [`BoxedUint`] +//! Support for serdect on [`BoxedUint`] use serdect::serde::{de, Deserialize, Deserializer, Serialize, Serializer}; From 30161968b0a2d4ef9626041eb1d60431d2381684 Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:14:27 +1100 Subject: [PATCH 09/11] Fix loading --- src/uint/boxed/encoding/serde.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/uint/boxed/encoding/serde.rs b/src/uint/boxed/encoding/serde.rs index 8656ecd96..636e14587 100644 --- a/src/uint/boxed/encoding/serde.rs +++ b/src/uint/boxed/encoding/serde.rs @@ -42,7 +42,7 @@ mod tests { #[test] fn serde() { #[allow(trivial_numeric_casts)] - let test: BoxedUint = BoxedUint::from(0x0011223344556677 as u64); + let test: BoxedUint = BoxedUint::from_be_hex("7711223344556600", 64).unwrap(); let serialized = bincode::serialize(&test).unwrap(); let deserialized: BoxedUint = bincode::deserialize(&serialized).unwrap(); @@ -53,7 +53,7 @@ mod tests { #[test] fn serde_owned() { #[allow(trivial_numeric_casts)] - let test: BoxedUint = BoxedUint::from(0x0011223344556677 as u64); + let test: BoxedUint = BoxedUint::from_be_hex("7711223344556600", 64).unwrap(); let serialized = bincode::serialize(&test).unwrap(); let deserialized: BoxedUint = bincode::deserialize_from(serialized.as_slice()).unwrap(); From 77889e4f7cbab061a20f616c285c11753382a064 Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:33:20 +1100 Subject: [PATCH 10/11] Address 32bit test variance --- src/uint/boxed/encoding/serde.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/uint/boxed/encoding/serde.rs b/src/uint/boxed/encoding/serde.rs index 636e14587..03bd26179 100644 --- a/src/uint/boxed/encoding/serde.rs +++ b/src/uint/boxed/encoding/serde.rs @@ -40,6 +40,7 @@ mod tests { use super::BoxedUint; #[test] + #[cfg(target_pointer_width = "64")] fn serde() { #[allow(trivial_numeric_casts)] let test: BoxedUint = BoxedUint::from_be_hex("7711223344556600", 64).unwrap(); @@ -51,6 +52,7 @@ mod tests { } #[test] + #[cfg(target_pointer_width = "64")] fn serde_owned() { #[allow(trivial_numeric_casts)] let test: BoxedUint = BoxedUint::from_be_hex("7711223344556600", 64).unwrap(); @@ -60,4 +62,19 @@ mod tests { assert_eq!(test, deserialized); } + + #[test] + #[cfg(target_pointer_width = "32")] + fn from_le_slice_eq() { + let test = hex!("7766554433221100"); + let box_uint = BoxedUint::from_le_slice(&bytes, 64).unwrap(); + + let serialized = bincode::serialize(&box_uint).unwrap(); + let deserialized: BoxedUint = bincode::deserialize_from(serialized.as_slice()).unwrap(); + + assert_eq!( + deserialized.as_limbs(), + &[Limb(0x44556677), Limb(0x00112233)] + ); + } } From e457c395a575d9a1777e29c5952096cf5ba9dfeb Mon Sep 17 00:00:00 2001 From: pinkforest <36498018+pinkforest@users.noreply.github.com> Date: Sat, 6 Apr 2024 16:35:15 +1100 Subject: [PATCH 11/11] Clear clippy lint --- src/uint/boxed/encoding/serde.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/uint/boxed/encoding/serde.rs b/src/uint/boxed/encoding/serde.rs index 03bd26179..81b7ecd7d 100644 --- a/src/uint/boxed/encoding/serde.rs +++ b/src/uint/boxed/encoding/serde.rs @@ -42,7 +42,6 @@ mod tests { #[test] #[cfg(target_pointer_width = "64")] fn serde() { - #[allow(trivial_numeric_casts)] let test: BoxedUint = BoxedUint::from_be_hex("7711223344556600", 64).unwrap(); let serialized = bincode::serialize(&test).unwrap(); @@ -54,7 +53,6 @@ mod tests { #[test] #[cfg(target_pointer_width = "64")] fn serde_owned() { - #[allow(trivial_numeric_casts)] let test: BoxedUint = BoxedUint::from_be_hex("7711223344556600", 64).unwrap(); let serialized = bincode::serialize(&test).unwrap();