bitcoin/taproot/
serialized_signature.rs

1//! Implements [`SerializedSignature`] and related types.
2//!
3//! Serialized Taproot signatures have the issue that they can have different lengths.
4//! We want to avoid using `Vec` since that would require allocations making the code slower and
5//! unable to run on platforms without an allocator. We implement a special type to encapsulate
6//! serialized signatures and since it's a bit more complicated it has its own module.
7
8use core::borrow::Borrow;
9use core::{fmt, ops};
10
11pub use into_iter::IntoIter;
12use io::Write;
13
14use super::{SigFromSliceError, Signature};
15
16pub(crate) const MAX_LEN: usize = 65; // 64 for sig, 1B sighash flag
17
18/// A serialized Taproot Signature
19#[derive(Copy, Clone)]
20pub struct SerializedSignature {
21    data: [u8; MAX_LEN],
22    len: usize,
23}
24
25impl fmt::Debug for SerializedSignature {
26    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
27}
28
29impl fmt::Display for SerializedSignature {
30    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
31        hex::fmt_hex_exact!(f, MAX_LEN, self, hex::Case::Lower)
32    }
33}
34
35impl PartialEq for SerializedSignature {
36    #[inline]
37    fn eq(&self, other: &SerializedSignature) -> bool { **self == **other }
38}
39
40impl PartialEq<[u8]> for SerializedSignature {
41    #[inline]
42    fn eq(&self, other: &[u8]) -> bool { **self == *other }
43}
44
45impl PartialEq<SerializedSignature> for [u8] {
46    #[inline]
47    fn eq(&self, other: &SerializedSignature) -> bool { *self == **other }
48}
49
50impl PartialOrd for SerializedSignature {
51    fn partial_cmp(&self, other: &SerializedSignature) -> Option<core::cmp::Ordering> {
52        Some((**self).cmp(&**other))
53    }
54}
55
56impl Ord for SerializedSignature {
57    fn cmp(&self, other: &SerializedSignature) -> core::cmp::Ordering { (**self).cmp(&**other) }
58}
59
60impl PartialOrd<[u8]> for SerializedSignature {
61    fn partial_cmp(&self, other: &[u8]) -> Option<core::cmp::Ordering> {
62        (**self).partial_cmp(other)
63    }
64}
65
66impl PartialOrd<SerializedSignature> for [u8] {
67    fn partial_cmp(&self, other: &SerializedSignature) -> Option<core::cmp::Ordering> {
68        self.partial_cmp(&**other)
69    }
70}
71
72impl core::hash::Hash for SerializedSignature {
73    fn hash<H: core::hash::Hasher>(&self, state: &mut H) { (**self).hash(state) }
74}
75
76impl AsRef<[u8]> for SerializedSignature {
77    #[inline]
78    fn as_ref(&self) -> &[u8] { self }
79}
80
81impl Borrow<[u8]> for SerializedSignature {
82    #[inline]
83    fn borrow(&self) -> &[u8] { self }
84}
85
86impl ops::Deref for SerializedSignature {
87    type Target = [u8];
88
89    #[inline]
90    fn deref(&self) -> &[u8] { &self.data[..self.len] }
91}
92
93impl Eq for SerializedSignature {}
94
95impl IntoIterator for SerializedSignature {
96    type IntoIter = IntoIter;
97    type Item = u8;
98
99    #[inline]
100    fn into_iter(self) -> Self::IntoIter { IntoIter::new(self) }
101}
102
103impl<'a> IntoIterator for &'a SerializedSignature {
104    type IntoIter = core::slice::Iter<'a, u8>;
105    type Item = &'a u8;
106
107    #[inline]
108    fn into_iter(self) -> Self::IntoIter { self.iter() }
109}
110
111impl From<Signature> for SerializedSignature {
112    fn from(value: Signature) -> Self { Self::from_signature(&value) }
113}
114
115impl<'a> From<&'a Signature> for SerializedSignature {
116    fn from(value: &'a Signature) -> Self { Self::from_signature(value) }
117}
118
119impl TryFrom<SerializedSignature> for Signature {
120    type Error = SigFromSliceError;
121
122    fn try_from(value: SerializedSignature) -> Result<Self, Self::Error> { value.to_signature() }
123}
124
125impl<'a> TryFrom<&'a SerializedSignature> for Signature {
126    type Error = SigFromSliceError;
127
128    fn try_from(value: &'a SerializedSignature) -> Result<Self, Self::Error> {
129        value.to_signature()
130    }
131}
132
133impl SerializedSignature {
134    /// Creates `SerializedSignature` from data and length.
135    ///
136    /// ## Panics
137    ///
138    /// If `len` > `MAX_LEN`
139    #[inline]
140    pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self {
141        assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN);
142        SerializedSignature { data, len }
143    }
144
145    /// Get the len of the used data.
146    // `len` is never 0, so `is_empty` would always return `false`.
147    #[allow(clippy::len_without_is_empty)]
148    #[inline]
149    pub fn len(&self) -> usize { self.len }
150
151    /// Set the length of the object.
152    #[inline]
153    pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
154
155    /// Convert the serialized signature into the Signature struct.
156    /// (This deserializes it)
157    #[inline]
158    pub fn to_signature(&self) -> Result<Signature, SigFromSliceError> {
159        Signature::from_slice(self)
160    }
161
162    /// Create a SerializedSignature from a Signature.
163    /// (this serializes it)
164    #[inline]
165    pub fn from_signature(sig: &Signature) -> SerializedSignature { sig.serialize() }
166
167    /// Writes this serialized signature to a `writer`.
168    #[inline]
169    pub fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> Result<(), io::Error> {
170        writer.write_all(self)
171    }
172}
173
174/// Separate mod to prevent outside code from accidentally breaking invariants.
175mod into_iter {
176    use super::*;
177
178    /// Owned iterator over the bytes of [`SerializedSignature`]
179    ///
180    /// Created by [`IntoIterator::into_iter`] method.
181    // allowed because of https://github.com/rust-lang/rust/issues/98348
182    #[allow(missing_copy_implementations)]
183    #[derive(Debug, Clone)]
184    pub struct IntoIter {
185        signature: SerializedSignature,
186        // invariant: pos <= signature.len()
187        pos: usize,
188    }
189
190    impl IntoIter {
191        #[inline]
192        pub(crate) fn new(signature: SerializedSignature) -> Self {
193            IntoIter {
194                signature,
195                // for all unsigned n: 0 <= n
196                pos: 0,
197            }
198        }
199
200        /// Returns the remaining bytes as a slice.
201        ///
202        /// This method is analogous to [`core::slice::Iter::as_slice`].
203        #[inline]
204        pub fn as_slice(&self) -> &[u8] { &self.signature[self.pos..] }
205    }
206
207    impl Iterator for IntoIter {
208        type Item = u8;
209
210        #[inline]
211        fn next(&mut self) -> Option<Self::Item> {
212            let byte = *self.signature.get(self.pos)?;
213            // can't overflow or break invariant because if pos is too large we return early
214            self.pos += 1;
215            Some(byte)
216        }
217
218        #[inline]
219        fn size_hint(&self) -> (usize, Option<usize>) {
220            // can't underlflow thanks to the invariant
221            let len = self.signature.len() - self.pos;
222            (len, Some(len))
223        }
224
225        // override for speed
226        #[inline]
227        fn nth(&mut self, n: usize) -> Option<Self::Item> {
228            if n >= self.len() {
229                // upholds invariant because the values will be equal
230                self.pos = self.signature.len();
231                None
232            } else {
233                // if n < signtature.len() - self.pos then n + self.pos < signature.len() which neither
234                // overflows nor breaks the invariant
235                self.pos += n;
236                self.next()
237            }
238        }
239    }
240
241    impl ExactSizeIterator for IntoIter {}
242
243    impl core::iter::FusedIterator for IntoIter {}
244
245    impl DoubleEndedIterator for IntoIter {
246        #[inline]
247        fn next_back(&mut self) -> Option<Self::Item> {
248            if self.pos == self.signature.len() {
249                return None;
250            }
251
252            // if len is 0 then pos is also 0 thanks to the invariant so we would return before we
253            // reach this
254            let new_len = self.signature.len() - 1;
255            let byte = self.signature[new_len];
256            self.signature.set_len_unchecked(new_len);
257            Some(byte)
258        }
259    }
260}
261
262#[cfg(test)]
263mod tests {
264    use super::{SerializedSignature, MAX_LEN};
265
266    #[test]
267    fn iterator_ops_are_homomorphic() {
268        let mut fake_signature_data = [0; MAX_LEN];
269        for (i, byte) in fake_signature_data.iter_mut().enumerate() {
270            *byte = i as u8;
271        }
272
273        let fake_signature = SerializedSignature { data: fake_signature_data, len: MAX_LEN };
274
275        let mut iter1 = fake_signature.into_iter();
276        let mut iter2 = fake_signature.iter();
277
278        // while let so we can compare size_hint and as_slice
279        while let (Some(a), Some(b)) = (iter1.next(), iter2.next()) {
280            assert_eq!(a, *b);
281            assert_eq!(iter1.size_hint(), iter2.size_hint());
282            assert_eq!(iter1.as_slice(), iter2.as_slice());
283        }
284
285        let mut iter1 = fake_signature.into_iter();
286        let mut iter2 = fake_signature.iter();
287
288        // manual next_back instead of rev() so that we can check as_slice()
289        // if next_back is implemented correctly then rev() is also correct - provided by `core`
290        while let (Some(a), Some(b)) = (iter1.next_back(), iter2.next_back()) {
291            assert_eq!(a, *b);
292            assert_eq!(iter1.size_hint(), iter2.size_hint());
293            assert_eq!(iter1.as_slice(), iter2.as_slice());
294        }
295    }
296}