Skip to main content

primitives/utils/codec/
legacy.rs

1//! Pre-#748 ("Rework serialization") serde encodings for [`InPlaceCodec`]-backed leaf types and
2//! the authenticated share/key/DaBit types built on them.
3
4use std::sync::Arc;
5
6use serde::{de::Error as DeError, Deserialize, Deserializer, Serialize, Serializer};
7
8use crate::{
9    algebra::{
10        elliptic_curve::{Curve, Point},
11        field::{FieldElement, FieldExtension, SubfieldElement},
12    },
13    correlated_randomness::dabits::DaBit,
14    sharing::authenticated::{PairwiseAuthKey, PairwiseAuthShare},
15    utils::codec::InPlaceCodec,
16};
17
18/// A type whose pre-#748 wire encoding can be recovered (and reproduced).
19pub trait LegacyBytes: Sized {
20    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>;
21    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>;
22}
23
24/// `#[serde(with = "…utils::codec::legacy")]` entry point.
25pub fn serialize<T: LegacyBytes, S: Serializer>(
26    value: &T,
27    serializer: S,
28) -> Result<S::Ok, S::Error> {
29    value.legacy_serialize(serializer)
30}
31
32/// `#[serde(with = "…utils::codec::legacy")]` entry point (also usable standalone as
33/// `#[serde(deserialize_with = "…utils::codec::legacy::deserialize")]` on read-only mirror types).
34pub fn deserialize<'de, T: LegacyBytes, D: Deserializer<'de>>(
35    deserializer: D,
36) -> Result<T, D::Error> {
37    T::legacy_deserialize(deserializer)
38}
39
40/// Adapter giving a [`LegacyBytes`] value plain `Serialize`/`Deserialize` impls, so derived
41/// container encodings (e.g. `Vec`'s, tuples') can be reused as-is instead of hand-rolling
42/// `SeqAccess` visitors.
43struct Legacy<T>(T);
44
45impl<T: LegacyBytes> Serialize for Legacy<&T> {
46    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
47        self.0.legacy_serialize(serializer)
48    }
49}
50
51impl<'de, T: LegacyBytes> Deserialize<'de> for Legacy<T> {
52    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
53        T::legacy_deserialize(deserializer).map(Legacy)
54    }
55}
56
57/// Field elements were `serde_bytes`-encoded canonical little-endian bytes.
58impl<F: FieldExtension> LegacyBytes for SubfieldElement<F> {
59    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
60        serde_bytes::serialize(AsRef::<[u8]>::as_ref(&self.to_le_bytes()), serializer)
61    }
62
63    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
64        let bytes: &[u8] = serde_bytes::deserialize(deserializer)?;
65        Self::from_le_bytes(bytes).map_err(DeError::custom)
66    }
67}
68
69/// Same encoding as [`SubfieldElement`] -- see its doc comment for why `to_le_bytes`, not
70/// `InPlaceCodec`.
71impl<F: FieldExtension> LegacyBytes for FieldElement<F> {
72    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
73        serde_bytes::serialize(AsRef::<[u8]>::as_ref(&self.to_le_bytes()), serializer)
74    }
75
76    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
77        let bytes: &[u8] = serde_bytes::deserialize(deserializer)?;
78        Self::from_le_bytes(bytes).map_err(DeError::custom)
79    }
80}
81
82/// Points were `serde_bytes`-encoded `GroupEncoding::to_bytes()` output. `InPlaceCodec` is the only
83/// public route to those bytes, and it reverses them for big-endian curves, so undo that to
84/// recover the original ordering.
85impl<C: Curve> LegacyBytes for Point<C> {
86    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
87        let mut bytes = self.to_inplace_bytes();
88        if C::POINT_BIG_ENDIAN {
89            bytes.reverse();
90        }
91        serde_bytes::serialize(bytes.as_slice(), serializer)
92    }
93
94    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
95        let bytes: &[u8] = serde_bytes::deserialize(deserializer)?;
96        let mut bytes = bytes.to_vec();
97        if C::POINT_BIG_ENDIAN {
98            bytes.reverse();
99        }
100        Self::read_le_bytes(&bytes).map_err(DeError::custom)
101    }
102}
103
104/// Batches were plain `Vec`s: a length, then each element in its own legacy encoding.
105impl<T: LegacyBytes> LegacyBytes for Vec<T> {
106    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
107        serializer.collect_seq(self.iter().map(Legacy))
108    }
109
110    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
111        Ok(Vec::<Legacy<T>>::deserialize(deserializer)?
112            .into_iter()
113            .map(|w| w.0)
114            .collect())
115    }
116}
117
118/// Same wire shape as `Vec<T>` (a length then each element) — used for `Wire`'s `Arc<[T]>` fields.
119impl<T: LegacyBytes> LegacyBytes for Arc<[T]> {
120    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
121        serializer.collect_seq(self.iter().map(Legacy))
122    }
123
124    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
125        Ok(Vec::<T>::legacy_deserialize(deserializer)?.into())
126    }
127}
128
129/// `alpha` (through `Arc`) then `beta`, each in its own legacy encoding.
130impl<A: LegacyBytes, B: LegacyBytes> LegacyBytes for PairwiseAuthKey<A, B> {
131    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
132        use serde::ser::SerializeTuple;
133        let mut tup = serializer.serialize_tuple(2)?;
134        tup.serialize_element(&Legacy(&*self.alpha))?;
135        tup.serialize_element(&Legacy(&self.beta))?;
136        tup.end()
137    }
138
139    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
140        let (alpha, beta) = <(Legacy<A>, Legacy<B>)>::deserialize(deserializer)?;
141        Ok(PairwiseAuthKey::new(Arc::new(alpha.0), beta.0))
142    }
143}
144
145/// `value`, then `macs` and `keys` as independently-length-prefixed sequences (unlike the current
146/// packed single-blob format — see the module docs).
147impl<V: LegacyBytes, A: LegacyBytes, B: LegacyBytes> LegacyBytes for PairwiseAuthShare<V, A, B> {
148    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
149        use serde::ser::SerializeTuple;
150        let mut tup = serializer.serialize_tuple(3)?;
151        tup.serialize_element(&Legacy(&self.value))?;
152        tup.serialize_element(&self.macs.iter().map(Legacy).collect::<Vec<_>>())?;
153        tup.serialize_element(&self.keys.iter().map(Legacy).collect::<Vec<_>>())?;
154        tup.end()
155    }
156
157    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
158        let (value, macs, keys) = <(
159            Legacy<V>,
160            Vec<Legacy<B>>,
161            Vec<Legacy<PairwiseAuthKey<A, B>>>,
162        )>::deserialize(deserializer)?;
163        // Not `try_new`: a trusted-dealer share legitimately has zero macs/keys and must still
164        // deserialize successfully, matching the current-format `Deserialize` impl's behavior.
165        Ok(PairwiseAuthShare {
166            value: value.0,
167            macs: macs.into_iter().map(|m| m.0).collect(),
168            keys: keys.into_iter().map(|k| k.0).collect(),
169        })
170    }
171}
172
173/// `bit` then `field`, each in its own legacy encoding.
174impl<F: FieldExtension> LegacyBytes for DaBit<F>
175where
176    crate::sharing::BitShare: LegacyBytes,
177    crate::sharing::FieldShare<F>: LegacyBytes,
178{
179    fn legacy_serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
180        use serde::ser::SerializeTuple;
181        let mut tup = serializer.serialize_tuple(2)?;
182        tup.serialize_element(&Legacy(&self.bit))?;
183        tup.serialize_element(&Legacy(&self.field))?;
184        tup.end()
185    }
186
187    fn legacy_deserialize<'de, D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
188        let (bit, field) = <(
189            Legacy<crate::sharing::BitShare>,
190            Legacy<crate::sharing::FieldShare<F>>,
191        )>::deserialize(deserializer)?;
192        Ok(DaBit::new(bit.0, field.0))
193    }
194}