ecdsa: Add to/from_signature, len, and iter
What changed, and why it matters
This commit is a routine API cleanup for the rust-bitcoin library. It adds a few helper methods (to_signature, from_signature, len, iter) to the ECDSA serialized-signature type and reorders existing methods in the Taproot serialized-signature type so both types look the same. There is no security fix or behavior change that would affect users' funds or data.
No security action needed. Treat as a normal API-refactoring commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch unifies the public API surface of ecdsa::SerializedSignature and taproot::SerializedSignature. It adds from_signature, to_signature, len, and iter to ecdsa::SerializedSignature, and reorders methods in taproot::SerializedSignature to match. It also changes the IntoIterator implementation for a reference to taproot::SerializedSignature from self.iter() to (**self).iter() so the new iter() method can be used consistently. No unsafe code, no boundary checks removed, no cryptographic logic changed, and no bug fixes are present.
Changed components
bitcoin/src/crypto/ecdsa.rsbitcoin/src/crypto/taproot.rsInspect captured patch +49 / −23
diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs
index 3f87d425..4bef63a6 100644
--- a/bitcoin/src/crypto/ecdsa.rs
+++ b/bitcoin/src/crypto/ecdsa.rs
@@ -111,6 +111,26 @@ pub struct SerializedSignature {
}
impl SerializedSignature {
+ /// Constructs a new SerializedSignature from a Signature.
+ ///
+ /// In other words this serializes a `Signature` into a `SerializedSignature`.
+ #[inline]
+ pub fn from_signature(sig: Signature) -> Self { sig.serialize() }
+
+ /// Converts the serialized signature into the [`Signature`] struct.
+ ///
+ /// In other words this deserializes the `SerializedSignature`.
+ #[inline]
+ pub fn to_signature(self) -> Result<Signature, DecodeError> {
+ Signature::from_slice(&self)
+ }
+
+ /// Returns the length of the serialized signature data.
+ #[inline]
+ // `len` is never 0, so `is_empty` would always return `false`.
+ #[allow(clippy::len_without_is_empty)]
+ pub fn len(&self) -> usize { self.len }
+
/// Returns an iterator over bytes of the signature.
#[inline]
pub fn iter(&self) -> core::slice::Iter<'_, u8> { self.into_iter() }
diff --git a/bitcoin/src/crypto/taproot.rs b/bitcoin/src/crypto/taproot.rs
index 9a5a2f34..d8d82635 100644
--- a/bitcoin/src/crypto/taproot.rs
+++ b/bitcoin/src/crypto/taproot.rs
@@ -7,7 +7,7 @@
use core::borrow::Borrow;
use core::convert::Infallible;
use core::ops::Deref;
-use core::{fmt, ops};
+use core::fmt;
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
@@ -99,44 +99,50 @@ pub struct SerializedSignature {
}
impl SerializedSignature {
- /// Constructs new `SerializedSignature` from data and length.
+ /// Constructs a new SerializedSignature from a Signature.
///
- /// # Panics
+ /// In other words this serializes a `Signature` into a `SerializedSignature`.
+ #[inline]
+ pub fn from_signature(sig: Signature) -> Self { sig.serialize() }
+
+ /// Converts the serialized signature into the [`Signature`] struct.
///
- /// If `len` > `MAX_LEN`
+ /// In other words this deserializes the `SerializedSignature`.
#[inline]
- pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self {
- assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN);
- Self { data, len }
+ pub fn to_signature(self) -> Result<Signature, SigFromSliceError> {
+ Signature::from_slice(&self)
}
- /// Get the len of the used data.
+ /// Returns the length of the serialized signature data.
+ #[inline]
// `len` is never 0, so `is_empty` would always return `false`.
#[allow(clippy::len_without_is_empty)]
- #[inline]
pub fn len(&self) -> usize { self.len }
- /// Set the length of the object.
+ /// Returns an iterator over bytes of the signature.
#[inline]
- pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
+ pub fn iter(&self) -> core::slice::Iter<'_, u8> { self.into_iter() }
- /// Convert the serialized signature into the Signature struct.
- /// (This deserializes it)
+ /// Writes this serialized signature to a `writer`.
#[inline]
- pub fn to_signature(self) -> Result<Signature, SigFromSliceError> {
- Signature::from_slice(&self)
+ pub fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> Result<(), io::Error> {
+ writer.write_all(self)
}
- /// Constructs a new SerializedSignature from a Signature.
- /// (this serializes it)
+ /// Constructs new `SerializedSignature` from data and length.
+ ///
+ /// # Panics
+ ///
+ /// If `len` > `MAX_LEN`
#[inline]
- pub fn from_signature(sig: Signature) -> Self { sig.serialize() }
+ pub(crate) fn from_raw_parts(data: [u8; MAX_LEN], len: usize) -> Self {
+ assert!(len <= MAX_LEN, "attempt to set length to {} but the maximum is {}", len, MAX_LEN);
+ Self { data, len }
+ }
- /// Writes this serialized signature to a `writer`.
+ /// Set the length of the object.
#[inline]
- pub fn write_to<W: Write + ?Sized>(&self, writer: &mut W) -> Result<(), io::Error> {
- writer.write_all(self)
- }
+ pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
}
impl fmt::Debug for SerializedSignature {
@@ -238,7 +244,7 @@ impl<'a> IntoIterator for &'a SerializedSignature {
type Item = &'a u8;
#[inline]
- fn into_iter(self) -> Self::IntoIter { self.iter() }
+ fn into_iter(self) -> Self::IntoIter { (**self).iter() }
}
impl From<Signature> for SerializedSignature {
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.