2022-06-29 04:05:31 +00:00
|
|
|
// SPDX-License-Identifier: CC0-1.0
|
2022-01-09 06:50:02 +00:00
|
|
|
|
|
|
|
//! ECDSA Bitcoin signatures.
|
|
|
|
//!
|
2023-10-30 21:36:09 +00:00
|
|
|
//! This module provides ECDSA signatures used by Bitcoin that can be roundtrip (de)serialized.
|
2022-01-09 06:50:02 +00:00
|
|
|
|
|
|
|
use core::str::FromStr;
|
2022-01-13 04:27:20 +00:00
|
|
|
use core::{fmt, iter};
|
2022-06-29 04:54:54 +00:00
|
|
|
|
2023-07-21 00:38:34 +00:00
|
|
|
use hex::FromHex;
|
2023-03-28 01:16:47 +00:00
|
|
|
use internals::write_err;
|
2022-06-29 04:54:54 +00:00
|
|
|
use secp256k1;
|
|
|
|
|
2022-12-05 23:39:56 +00:00
|
|
|
use crate::prelude::*;
|
2023-02-18 11:43:13 +00:00
|
|
|
use crate::script::PushBytes;
|
2023-05-18 05:11:26 +00:00
|
|
|
use crate::sighash::{EcdsaSighashType, NonStandardSighashTypeError};
|
2022-01-09 06:50:02 +00:00
|
|
|
|
2023-02-18 11:31:07 +00:00
|
|
|
const MAX_SIG_LEN: usize = 73;
|
|
|
|
|
2022-01-09 06:50:02 +00:00
|
|
|
/// An ECDSA signature with the corresponding hash type.
|
2022-05-06 03:37:24 +00:00
|
|
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
2022-01-09 06:50:02 +00:00
|
|
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
2022-05-25 06:41:59 +00:00
|
|
|
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
|
2022-11-08 00:36:52 +00:00
|
|
|
pub struct Signature {
|
2022-01-09 06:50:02 +00:00
|
|
|
/// The underlying ECDSA Signature
|
|
|
|
pub sig: secp256k1::ecdsa::Signature,
|
|
|
|
/// The corresponding hash type
|
2022-03-28 21:48:53 +00:00
|
|
|
pub hash_ty: EcdsaSighashType,
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-11-08 00:36:52 +00:00
|
|
|
impl Signature {
|
2023-10-30 21:37:11 +00:00
|
|
|
/// Constructs an ECDSA Bitcoin signature for [`EcdsaSighashType::All`].
|
2022-11-08 00:36:52 +00:00
|
|
|
pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> Signature {
|
2022-12-05 23:39:56 +00:00
|
|
|
Signature { sig, hash_ty: EcdsaSighashType::All }
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-01-07 02:58:47 +00:00
|
|
|
/// Deserializes from slice following the standardness rules for [`EcdsaSighashType`].
|
2022-11-08 00:36:52 +00:00
|
|
|
pub fn from_slice(sl: &[u8]) -> Result<Self, Error> {
|
2022-12-05 23:39:56 +00:00
|
|
|
let (hash_ty, sig) = sl.split_last().ok_or(Error::EmptySignature)?;
|
2023-05-18 05:28:31 +00:00
|
|
|
let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32)?;
|
2022-12-05 23:39:56 +00:00
|
|
|
let sig = secp256k1::ecdsa::Signature::from_der(sig).map_err(Error::Secp256k1)?;
|
2022-11-08 00:36:52 +00:00
|
|
|
Ok(Signature { sig, hash_ty })
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|
|
|
|
|
2022-01-07 02:58:47 +00:00
|
|
|
/// Serializes an ECDSA signature (inner secp256k1 signature in DER format).
|
2023-02-18 11:31:07 +00:00
|
|
|
///
|
|
|
|
/// This does **not** perform extra heap allocation.
|
|
|
|
pub fn serialize(&self) -> SerializedSignature {
|
|
|
|
let mut buf = [0u8; MAX_SIG_LEN];
|
|
|
|
let signature = self.sig.serialize_der();
|
|
|
|
buf[..signature.len()].copy_from_slice(&signature);
|
|
|
|
buf[signature.len()] = self.hash_ty as u8;
|
2022-12-05 23:39:56 +00:00
|
|
|
SerializedSignature { data: buf, len: signature.len() + 1 }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Serializes an ECDSA signature (inner secp256k1 signature in DER format) into `Vec`.
|
|
|
|
///
|
|
|
|
/// Note: this performs an extra heap allocation, you might prefer the
|
|
|
|
/// [`serialize`](Self::serialize) method instead.
|
2022-08-01 22:33:22 +00:00
|
|
|
pub fn to_vec(self) -> Vec<u8> {
|
2022-01-09 06:50:02 +00:00
|
|
|
// TODO: add support to serialize to a writer to SerializedSig
|
2022-12-05 23:39:56 +00:00
|
|
|
self.sig.serialize_der().iter().copied().chain(iter::once(self.hash_ty as u8)).collect()
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-08 00:36:52 +00:00
|
|
|
impl fmt::Display for Signature {
|
2022-01-09 06:50:02 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2023-01-07 15:39:11 +00:00
|
|
|
fmt::LowerHex::fmt(&self.sig.serialize_der().as_hex(), f)?;
|
|
|
|
fmt::LowerHex::fmt(&[self.hash_ty as u8].as_hex(), f)
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-08 00:36:52 +00:00
|
|
|
impl FromStr for Signature {
|
|
|
|
type Err = Error;
|
2022-01-09 06:50:02 +00:00
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
let bytes = Vec::from_hex(s)?;
|
2022-12-05 23:39:56 +00:00
|
|
|
let (sighash_byte, signature) = bytes.split_last().ok_or(Error::EmptySignature)?;
|
2022-11-08 00:36:52 +00:00
|
|
|
Ok(Signature {
|
2022-01-09 06:50:02 +00:00
|
|
|
sig: secp256k1::ecdsa::Signature::from_der(signature)?,
|
2022-12-05 23:39:56 +00:00
|
|
|
hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)?,
|
2022-01-09 06:50:02 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-18 11:31:07 +00:00
|
|
|
/// Holds signature serialized in-line (not in `Vec`).
|
|
|
|
///
|
|
|
|
/// This avoids allocation and allows proving maximum size of the signature (73 bytes).
|
|
|
|
/// The type can be used largely as a byte slice. It implements all standard traits one would
|
|
|
|
/// expect and has familiar methods.
|
2023-02-18 11:43:13 +00:00
|
|
|
/// However, the usual use case is to push it into a script. This can be done directly passing it
|
|
|
|
/// into [`push_slice`](crate::script::ScriptBuf::push_slice).
|
2023-02-18 11:31:07 +00:00
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub struct SerializedSignature {
|
|
|
|
data: [u8; MAX_SIG_LEN],
|
|
|
|
len: usize,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SerializedSignature {
|
|
|
|
/// Returns an iterator over bytes of the signature.
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
pub fn iter(&self) -> core::slice::Iter<'_, u8> { self.into_iter() }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl core::ops::Deref for SerializedSignature {
|
|
|
|
type Target = [u8];
|
|
|
|
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
fn deref(&self) -> &Self::Target { &self.data[..self.len] }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl core::ops::DerefMut for SerializedSignature {
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.data[..self.len] }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AsRef<[u8]> for SerializedSignature {
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
fn as_ref(&self) -> &[u8] { self }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AsMut<[u8]> for SerializedSignature {
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
fn as_mut(&mut self) -> &mut [u8] { self }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
2023-02-18 11:43:13 +00:00
|
|
|
impl AsRef<PushBytes> for SerializedSignature {
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
fn as_ref(&self) -> &PushBytes { &<&PushBytes>::from(&self.data)[..self.len()] }
|
2023-02-18 11:43:13 +00:00
|
|
|
}
|
|
|
|
|
2023-02-18 11:31:07 +00:00
|
|
|
impl core::borrow::Borrow<[u8]> for SerializedSignature {
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
fn borrow(&self) -> &[u8] { self }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl core::borrow::BorrowMut<[u8]> for SerializedSignature {
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
fn borrow_mut(&mut self) -> &mut [u8] { self }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for SerializedSignature {
|
|
|
|
#[inline]
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self, f) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for SerializedSignature {
|
|
|
|
#[inline]
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self, f) }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::LowerHex for SerializedSignature {
|
|
|
|
#[inline]
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fmt::LowerHex::fmt(&(**self).as_hex(), f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::UpperHex for SerializedSignature {
|
|
|
|
#[inline]
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
fmt::UpperHex::fmt(&(**self).as_hex(), f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PartialEq for SerializedSignature {
|
|
|
|
#[inline]
|
|
|
|
fn eq(&self, other: &SerializedSignature) -> bool { **self == **other }
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for SerializedSignature {}
|
|
|
|
|
|
|
|
impl core::hash::Hash for SerializedSignature {
|
2022-12-05 23:39:56 +00:00
|
|
|
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { core::hash::Hash::hash(&**self, state) }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> IntoIterator for &'a SerializedSignature {
|
|
|
|
type IntoIter = core::slice::Iter<'a, u8>;
|
|
|
|
type Item = &'a u8;
|
|
|
|
|
|
|
|
#[inline]
|
2022-12-05 23:39:56 +00:00
|
|
|
fn into_iter(self) -> Self::IntoIter { (*self).iter() }
|
2023-02-18 11:31:07 +00:00
|
|
|
}
|
|
|
|
|
2023-05-18 06:00:13 +00:00
|
|
|
/// An ECDSA signature-related error.
|
2023-07-27 01:10:22 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
2022-05-31 04:29:50 +00:00
|
|
|
#[non_exhaustive]
|
2022-11-08 00:36:52 +00:00
|
|
|
pub enum Error {
|
2023-08-01 06:16:28 +00:00
|
|
|
/// Hex decoding error.
|
2023-07-21 00:38:34 +00:00
|
|
|
Hex(hex::HexToBytesError),
|
2023-08-01 06:16:28 +00:00
|
|
|
/// Non-standard sighash type.
|
2023-05-18 05:28:31 +00:00
|
|
|
SighashType(NonStandardSighashTypeError),
|
2023-08-01 06:16:28 +00:00
|
|
|
/// Signature was empty.
|
2022-01-09 06:50:02 +00:00
|
|
|
EmptySignature,
|
2023-08-01 06:16:28 +00:00
|
|
|
/// A secp256k1 error.
|
2022-01-09 06:50:02 +00:00
|
|
|
Secp256k1(secp256k1::Error),
|
|
|
|
}
|
|
|
|
|
2022-11-08 00:36:52 +00:00
|
|
|
impl fmt::Display for Error {
|
2022-01-09 06:50:02 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2023-05-18 05:15:02 +00:00
|
|
|
use Error::*;
|
|
|
|
|
2022-01-09 06:50:02 +00:00
|
|
|
match *self {
|
2023-05-18 05:15:02 +00:00
|
|
|
Hex(ref e) => write_err!(f, "signature hex decoding error"; e),
|
2023-05-18 05:28:31 +00:00
|
|
|
SighashType(ref e) => write_err!(f, "non-standard signature hash type"; e),
|
2023-05-18 05:15:02 +00:00
|
|
|
EmptySignature => write!(f, "empty ECDSA signature"),
|
2023-05-18 06:19:37 +00:00
|
|
|
Secp256k1(ref e) => write_err!(f, "secp256k1"; e),
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "std")]
|
2022-11-08 00:36:52 +00:00
|
|
|
impl std::error::Error for Error {
|
2022-05-04 05:56:24 +00:00
|
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
Make error types uniform
On our way to v1.0.0 we are defining a standard for our error types,
this includes:
- Uses the following derives (unless not possible, usually because of `io::Error`)
`#[derive(Debug, Clone, PartialEq, Eq)]`
- Has `non_exhaustive` unless we really know we can commit to not adding
anything.
Furthermore, we are trying to make the codebase easy to read. Error code
is write-once-read-many (well it should be) so if we make all the error
code super uniform the users can flick to an error and quickly see what
it includes. In an effort to achieve this I have made up a style and
over recent times have change much of the error code to that new style,
this PR audits _all_ error types in the code base and enforces the
style, specifically:
- Is layed out: definition, [impl block], Display impl, error::Error impl, From impls
- `error::Error` impl matches on enum even if it returns `None` for all variants
- Display/Error impls import enum variants locally
- match uses *self and `ref e`
- error::Error variants that return `Some` come first, `None` after
Re: non_exhaustive
To make dev and review easier I have added `non_exhaustive` to _every_
error type. We can then remove it error by error as we see fit. This is
because it takes a bit of thinking to do and review where as this patch
should not take much brain power to review.
2023-10-04 02:55:45 +00:00
|
|
|
use Error::*;
|
2022-05-04 05:56:24 +00:00
|
|
|
|
Make error types uniform
On our way to v1.0.0 we are defining a standard for our error types,
this includes:
- Uses the following derives (unless not possible, usually because of `io::Error`)
`#[derive(Debug, Clone, PartialEq, Eq)]`
- Has `non_exhaustive` unless we really know we can commit to not adding
anything.
Furthermore, we are trying to make the codebase easy to read. Error code
is write-once-read-many (well it should be) so if we make all the error
code super uniform the users can flick to an error and quickly see what
it includes. In an effort to achieve this I have made up a style and
over recent times have change much of the error code to that new style,
this PR audits _all_ error types in the code base and enforces the
style, specifically:
- Is layed out: definition, [impl block], Display impl, error::Error impl, From impls
- `error::Error` impl matches on enum even if it returns `None` for all variants
- Display/Error impls import enum variants locally
- match uses *self and `ref e`
- error::Error variants that return `Some` come first, `None` after
Re: non_exhaustive
To make dev and review easier I have added `non_exhaustive` to _every_
error type. We can then remove it error by error as we see fit. This is
because it takes a bit of thinking to do and review where as this patch
should not take much brain power to review.
2023-10-04 02:55:45 +00:00
|
|
|
match *self {
|
|
|
|
Hex(ref e) => Some(e),
|
|
|
|
Secp256k1(ref e) => Some(e),
|
|
|
|
SighashType(ref e) => Some(e),
|
2023-05-18 05:28:31 +00:00
|
|
|
EmptySignature => None,
|
2022-05-04 05:56:24 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-09 06:50:02 +00:00
|
|
|
|
2022-11-08 00:36:52 +00:00
|
|
|
impl From<secp256k1::Error> for Error {
|
2022-12-05 23:39:56 +00:00
|
|
|
fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) }
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|
|
|
|
|
2023-05-18 05:11:26 +00:00
|
|
|
impl From<NonStandardSighashTypeError> for Error {
|
2023-05-18 05:28:31 +00:00
|
|
|
fn from(err: NonStandardSighashTypeError) -> Self { Error::SighashType(err) }
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|
|
|
|
|
2023-07-21 00:38:34 +00:00
|
|
|
impl From<hex::HexToBytesError> for Error {
|
|
|
|
fn from(err: hex::HexToBytesError) -> Self { Error::Hex(err) }
|
2022-01-09 06:50:02 +00:00
|
|
|
}
|