crypto: Run the formatter
Run `cargo +nightly fmt`, no other manual changes.
This commit is contained in:
parent
c8a3c58786
commit
3ec8a12428
|
@ -8,14 +8,14 @@
|
||||||
use core::str::FromStr;
|
use core::str::FromStr;
|
||||||
use core::{fmt, iter};
|
use core::{fmt, iter};
|
||||||
|
|
||||||
use bitcoin_internals::write_err;
|
|
||||||
use bitcoin_internals::hex::display::DisplayHex;
|
use bitcoin_internals::hex::display::DisplayHex;
|
||||||
|
use bitcoin_internals::write_err;
|
||||||
use secp256k1;
|
use secp256k1;
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
use crate::hashes::hex::{self, FromHex};
|
use crate::hashes::hex::{self, FromHex};
|
||||||
use crate::sighash::{EcdsaSighashType, NonStandardSighashType};
|
use crate::prelude::*;
|
||||||
use crate::script::PushBytes;
|
use crate::script::PushBytes;
|
||||||
|
use crate::sighash::{EcdsaSighashType, NonStandardSighashType};
|
||||||
|
|
||||||
const MAX_SIG_LEN: usize = 73;
|
const MAX_SIG_LEN: usize = 73;
|
||||||
|
|
||||||
|
@ -33,20 +33,15 @@ pub struct Signature {
|
||||||
impl Signature {
|
impl Signature {
|
||||||
/// Constructs an ECDSA bitcoin signature for [`EcdsaSighashType::All`].
|
/// Constructs an ECDSA bitcoin signature for [`EcdsaSighashType::All`].
|
||||||
pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> Signature {
|
pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> Signature {
|
||||||
Signature {
|
Signature { sig, hash_ty: EcdsaSighashType::All }
|
||||||
sig,
|
|
||||||
hash_ty: EcdsaSighashType::All
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes from slice following the standardness rules for [`EcdsaSighashType`].
|
/// Deserializes from slice following the standardness rules for [`EcdsaSighashType`].
|
||||||
pub fn from_slice(sl: &[u8]) -> Result<Self, Error> {
|
pub fn from_slice(sl: &[u8]) -> Result<Self, Error> {
|
||||||
let (hash_ty, sig) = sl.split_last()
|
let (hash_ty, sig) = sl.split_last().ok_or(Error::EmptySignature)?;
|
||||||
.ok_or(Error::EmptySignature)?;
|
|
||||||
let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32)
|
let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32)
|
||||||
.map_err(|_| Error::NonStandardSighashType(*hash_ty as u32))?;
|
.map_err(|_| Error::NonStandardSighashType(*hash_ty as u32))?;
|
||||||
let sig = secp256k1::ecdsa::Signature::from_der(sig)
|
let sig = secp256k1::ecdsa::Signature::from_der(sig).map_err(Error::Secp256k1)?;
|
||||||
.map_err(Error::Secp256k1)?;
|
|
||||||
Ok(Signature { sig, hash_ty })
|
Ok(Signature { sig, hash_ty })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +53,7 @@ impl Signature {
|
||||||
let signature = self.sig.serialize_der();
|
let signature = self.sig.serialize_der();
|
||||||
buf[..signature.len()].copy_from_slice(&signature);
|
buf[..signature.len()].copy_from_slice(&signature);
|
||||||
buf[signature.len()] = self.hash_ty as u8;
|
buf[signature.len()] = self.hash_ty as u8;
|
||||||
SerializedSignature {
|
SerializedSignature { data: buf, len: signature.len() + 1 }
|
||||||
data: buf,
|
|
||||||
len: signature.len() + 1,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes an ECDSA signature (inner secp256k1 signature in DER format) into `Vec`.
|
/// Serializes an ECDSA signature (inner secp256k1 signature in DER format) into `Vec`.
|
||||||
|
@ -70,10 +62,7 @@ impl Signature {
|
||||||
/// [`serialize`](Self::serialize) method instead.
|
/// [`serialize`](Self::serialize) method instead.
|
||||||
pub fn to_vec(self) -> Vec<u8> {
|
pub fn to_vec(self) -> Vec<u8> {
|
||||||
// TODO: add support to serialize to a writer to SerializedSig
|
// TODO: add support to serialize to a writer to SerializedSig
|
||||||
self.sig.serialize_der()
|
self.sig.serialize_der().iter().copied().chain(iter::once(self.hash_ty as u8)).collect()
|
||||||
.iter().copied()
|
|
||||||
.chain(iter::once(self.hash_ty as u8))
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,11 +78,10 @@ impl FromStr for Signature {
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let bytes = Vec::from_hex(s)?;
|
let bytes = Vec::from_hex(s)?;
|
||||||
let (sighash_byte, signature) = bytes.split_last()
|
let (sighash_byte, signature) = bytes.split_last().ok_or(Error::EmptySignature)?;
|
||||||
.ok_or(Error::EmptySignature)?;
|
|
||||||
Ok(Signature {
|
Ok(Signature {
|
||||||
sig: secp256k1::ecdsa::Signature::from_der(signature)?,
|
sig: secp256k1::ecdsa::Signature::from_der(signature)?,
|
||||||
hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)?
|
hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,60 +102,44 @@ pub struct SerializedSignature {
|
||||||
impl SerializedSignature {
|
impl SerializedSignature {
|
||||||
/// Returns an iterator over bytes of the signature.
|
/// Returns an iterator over bytes of the signature.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter(&self) -> core::slice::Iter<'_, u8> {
|
pub fn iter(&self) -> core::slice::Iter<'_, u8> { self.into_iter() }
|
||||||
self.into_iter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::ops::Deref for SerializedSignature {
|
impl core::ops::Deref for SerializedSignature {
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target { &self.data[..self.len] }
|
||||||
&self.data[..self.len]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::ops::DerefMut for SerializedSignature {
|
impl core::ops::DerefMut for SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.data[..self.len] }
|
||||||
&mut self.data[..self.len]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<[u8]> for SerializedSignature {
|
impl AsRef<[u8]> for SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] { self }
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsMut<[u8]> for SerializedSignature {
|
impl AsMut<[u8]> for SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_mut(&mut self) -> &mut [u8] {
|
fn as_mut(&mut self) -> &mut [u8] { self }
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRef<PushBytes> for SerializedSignature {
|
impl AsRef<PushBytes> for SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ref(&self) -> &PushBytes {
|
fn as_ref(&self) -> &PushBytes { &<&PushBytes>::from(&self.data)[..self.len()] }
|
||||||
&<&PushBytes>::from(&self.data)[..self.len()]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::borrow::Borrow<[u8]> for SerializedSignature {
|
impl core::borrow::Borrow<[u8]> for SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn borrow(&self) -> &[u8] {
|
fn borrow(&self) -> &[u8] { self }
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::borrow::BorrowMut<[u8]> for SerializedSignature {
|
impl core::borrow::BorrowMut<[u8]> for SerializedSignature {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn borrow_mut(&mut self) -> &mut [u8] {
|
fn borrow_mut(&mut self) -> &mut [u8] { self }
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for SerializedSignature {
|
impl fmt::Debug for SerializedSignature {
|
||||||
|
@ -202,9 +174,7 @@ impl PartialEq for SerializedSignature {
|
||||||
impl Eq for SerializedSignature {}
|
impl Eq for SerializedSignature {}
|
||||||
|
|
||||||
impl core::hash::Hash for SerializedSignature {
|
impl core::hash::Hash for SerializedSignature {
|
||||||
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: core::hash::Hasher>(&self, state: &mut H) { core::hash::Hash::hash(&**self, state) }
|
||||||
core::hash::Hash::hash(&**self, state)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a SerializedSignature {
|
impl<'a> IntoIterator for &'a SerializedSignature {
|
||||||
|
@ -212,9 +182,7 @@ impl<'a> IntoIterator for &'a SerializedSignature {
|
||||||
type Item = &'a u8;
|
type Item = &'a u8;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter { (*self).iter() }
|
||||||
(*self).iter()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A key-related error.
|
/// A key-related error.
|
||||||
|
@ -231,18 +199,14 @@ pub enum Error {
|
||||||
Secp256k1(secp256k1::Error),
|
Secp256k1(secp256k1::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Error::HexEncoding(ref e) =>
|
Error::HexEncoding(ref e) => write_err!(f, "Signature hex encoding error"; e),
|
||||||
write_err!(f, "Signature hex encoding error"; e),
|
|
||||||
Error::NonStandardSighashType(hash_ty) =>
|
Error::NonStandardSighashType(hash_ty) =>
|
||||||
write!(f, "Non standard signature hash type {}", hash_ty),
|
write!(f, "Non standard signature hash type {}", hash_ty),
|
||||||
Error::EmptySignature =>
|
Error::EmptySignature => write!(f, "Empty ECDSA signature"),
|
||||||
write!(f, "Empty ECDSA signature"),
|
Error::Secp256k1(ref e) => write_err!(f, "invalid ECDSA signature"; e),
|
||||||
Error::Secp256k1(ref e) =>
|
|
||||||
write_err!(f, "invalid ECDSA signature"; e),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,19 +226,13 @@ impl std::error::Error for Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<secp256k1::Error> for Error {
|
impl From<secp256k1::Error> for Error {
|
||||||
fn from(e: secp256k1::Error) -> Error {
|
fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) }
|
||||||
Error::Secp256k1(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NonStandardSighashType> for Error {
|
impl From<NonStandardSighashType> for Error {
|
||||||
fn from(err: NonStandardSighashType) -> Self {
|
fn from(err: NonStandardSighashType) -> Self { Error::NonStandardSighashType(err.0) }
|
||||||
Error::NonStandardSighashType(err.0)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<hex::Error> for Error {
|
impl From<hex::Error> for Error {
|
||||||
fn from(err: hex::Error) -> Self {
|
fn from(err: hex::Error) -> Self { Error::HexEncoding(err) }
|
||||||
Error::HexEncoding(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,20 @@
|
||||||
//! This module provides keys used in Bitcoin that can be roundtrip
|
//! This module provides keys used in Bitcoin that can be roundtrip
|
||||||
//! (de)serialized.
|
//! (de)serialized.
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
use core::{ops, str::FromStr};
|
|
||||||
use core::fmt::{self, Write};
|
use core::fmt::{self, Write};
|
||||||
|
use core::ops;
|
||||||
|
use core::str::FromStr;
|
||||||
|
|
||||||
use bitcoin_internals::write_err;
|
use bitcoin_internals::write_err;
|
||||||
|
pub use secp256k1::{self, constants, KeyPair, Parity, Secp256k1, Verification, XOnlyPublicKey};
|
||||||
|
|
||||||
pub use secp256k1::{self, constants, Secp256k1, KeyPair, XOnlyPublicKey, Verification, Parity};
|
|
||||||
|
|
||||||
use crate::{base58, io};
|
|
||||||
use crate::network::constants::Network;
|
|
||||||
use crate::hashes::{Hash, hash160, hex, hex::FromHex};
|
|
||||||
use crate::hash_types::{PubkeyHash, WPubkeyHash};
|
use crate::hash_types::{PubkeyHash, WPubkeyHash};
|
||||||
|
use crate::hashes::hex::FromHex;
|
||||||
|
use crate::hashes::{hash160, hex, Hash};
|
||||||
|
use crate::network::constants::Network;
|
||||||
|
use crate::prelude::*;
|
||||||
use crate::taproot::{TapNodeHash, TapTweakHash};
|
use crate::taproot::{TapNodeHash, TapTweakHash};
|
||||||
|
use crate::{base58, io};
|
||||||
|
|
||||||
/// A key-related error.
|
/// A key-related error.
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
@ -44,7 +44,8 @@ impl fmt::Display for Error {
|
||||||
Error::Secp256k1(ref e) => write_err!(f, "key secp256k1 error"; e),
|
Error::Secp256k1(ref e) => write_err!(f, "key secp256k1 error"; e),
|
||||||
Error::InvalidKeyPrefix(ref b) => write!(f, "key prefix invalid: {}", b),
|
Error::InvalidKeyPrefix(ref b) => write!(f, "key prefix invalid: {}", b),
|
||||||
Error::Hex(ref e) => write_err!(f, "key hex decoding error"; e),
|
Error::Hex(ref e) => write_err!(f, "key hex decoding error"; e),
|
||||||
Error::InvalidHexLength(got) => write!(f, "PublicKey hex should be 66 or 130 digits long, got: {}", got),
|
Error::InvalidHexLength(got) =>
|
||||||
|
write!(f, "PublicKey hex should be 66 or 130 digits long, got: {}", got),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,26 +67,19 @@ impl std::error::Error for Error {
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl From<base58::Error> for Error {
|
impl From<base58::Error> for Error {
|
||||||
fn from(e: base58::Error) -> Error {
|
fn from(e: base58::Error) -> Error { Error::Base58(e) }
|
||||||
Error::Base58(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl From<secp256k1::Error> for Error {
|
impl From<secp256k1::Error> for Error {
|
||||||
fn from(e: secp256k1::Error) -> Error {
|
fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) }
|
||||||
Error::Secp256k1(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
impl From<hex::Error> for Error {
|
impl From<hex::Error> for Error {
|
||||||
fn from(e: hex::Error) -> Self {
|
fn from(e: hex::Error) -> Self { Error::Hex(e) }
|
||||||
Error::Hex(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// A Bitcoin ECDSA public key
|
/// A Bitcoin ECDSA public key
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct PublicKey {
|
pub struct PublicKey {
|
||||||
|
@ -98,19 +92,13 @@ pub struct PublicKey {
|
||||||
impl PublicKey {
|
impl PublicKey {
|
||||||
/// Constructs compressed ECDSA public key from the provided generic Secp256k1 public key
|
/// Constructs compressed ECDSA public key from the provided generic Secp256k1 public key
|
||||||
pub fn new(key: impl Into<secp256k1::PublicKey>) -> PublicKey {
|
pub fn new(key: impl Into<secp256k1::PublicKey>) -> PublicKey {
|
||||||
PublicKey {
|
PublicKey { compressed: true, inner: key.into() }
|
||||||
compressed: true,
|
|
||||||
inner: key.into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs uncompressed (legacy) ECDSA public key from the provided generic Secp256k1
|
/// Constructs uncompressed (legacy) ECDSA public key from the provided generic Secp256k1
|
||||||
/// public key
|
/// public key
|
||||||
pub fn new_uncompressed(key: impl Into<secp256k1::PublicKey>) -> PublicKey {
|
pub fn new_uncompressed(key: impl Into<secp256k1::PublicKey>) -> PublicKey {
|
||||||
PublicKey {
|
PublicKey { compressed: false, inner: key.into() }
|
||||||
compressed: false,
|
|
||||||
inner: key.into(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_serialized<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
fn with_serialized<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
|
||||||
|
@ -122,15 +110,13 @@ impl PublicKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns bitcoin 160-bit hash of the public key
|
/// Returns bitcoin 160-bit hash of the public key
|
||||||
pub fn pubkey_hash(&self) -> PubkeyHash {
|
pub fn pubkey_hash(&self) -> PubkeyHash { self.with_serialized(PubkeyHash::hash) }
|
||||||
self.with_serialized(PubkeyHash::hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns bitcoin 160-bit hash of the public key for witness program
|
/// Returns bitcoin 160-bit hash of the public key for witness program
|
||||||
pub fn wpubkey_hash(&self) -> Option<WPubkeyHash> {
|
pub fn wpubkey_hash(&self) -> Option<WPubkeyHash> {
|
||||||
if self.compressed {
|
if self.compressed {
|
||||||
Some(WPubkeyHash::from_byte_array(
|
Some(WPubkeyHash::from_byte_array(
|
||||||
hash160::Hash::hash(&self.inner.serialize()).to_byte_array()
|
hash160::Hash::hash(&self.inner.serialize()).to_byte_array(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
// We can't create witness pubkey hashes for an uncompressed
|
// We can't create witness pubkey hashes for an uncompressed
|
||||||
|
@ -249,26 +235,25 @@ impl PublicKey {
|
||||||
let compressed = match data.len() {
|
let compressed = match data.len() {
|
||||||
33 => true,
|
33 => true,
|
||||||
65 => false,
|
65 => false,
|
||||||
len => {
|
len => {
|
||||||
return Err(base58::Error::InvalidLength(len).into());
|
return Err(base58::Error::InvalidLength(len).into());
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !compressed && data[0] != 0x04 {
|
if !compressed && data[0] != 0x04 {
|
||||||
return Err(Error::InvalidKeyPrefix(data[0]))
|
return Err(Error::InvalidKeyPrefix(data[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PublicKey {
|
Ok(PublicKey { compressed, inner: secp256k1::PublicKey::from_slice(data)? })
|
||||||
compressed,
|
|
||||||
inner: secp256k1::PublicKey::from_slice(data)?,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the public key as supposed to be used with this secret
|
/// Computes the public key as supposed to be used with this secret
|
||||||
pub fn from_private_key<C: secp256k1::Signing>(secp: &Secp256k1<C>, sk: &PrivateKey) -> PublicKey {
|
pub fn from_private_key<C: secp256k1::Signing>(
|
||||||
|
secp: &Secp256k1<C>,
|
||||||
|
sk: &PrivateKey,
|
||||||
|
) -> PublicKey {
|
||||||
sk.public_key(secp)
|
sk.public_key(secp)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An opaque return type for PublicKey::to_sort_key
|
/// An opaque return type for PublicKey::to_sort_key
|
||||||
|
@ -299,9 +284,7 @@ impl FromStr for PublicKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<PublicKey> for PubkeyHash {
|
impl From<PublicKey> for PubkeyHash {
|
||||||
fn from(key: PublicKey) -> PubkeyHash {
|
fn from(key: PublicKey) -> PubkeyHash { key.pubkey_hash() }
|
||||||
key.pubkey_hash()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A Bitcoin ECDSA private key
|
/// A Bitcoin ECDSA private key
|
||||||
|
@ -320,35 +303,25 @@ impl PrivateKey {
|
||||||
/// Constructs compressed ECDSA private key from the provided generic Secp256k1 private key
|
/// Constructs compressed ECDSA private key from the provided generic Secp256k1 private key
|
||||||
/// and the specified network
|
/// and the specified network
|
||||||
pub fn new(key: secp256k1::SecretKey, network: Network) -> PrivateKey {
|
pub fn new(key: secp256k1::SecretKey, network: Network) -> PrivateKey {
|
||||||
PrivateKey {
|
PrivateKey { compressed: true, network, inner: key }
|
||||||
compressed: true,
|
|
||||||
network,
|
|
||||||
inner: key,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs uncompressed (legacy) ECDSA private key from the provided generic Secp256k1
|
/// Constructs uncompressed (legacy) ECDSA private key from the provided generic Secp256k1
|
||||||
/// private key and the specified network
|
/// private key and the specified network
|
||||||
pub fn new_uncompressed(key: secp256k1::SecretKey, network: Network) -> PrivateKey {
|
pub fn new_uncompressed(key: secp256k1::SecretKey, network: Network) -> PrivateKey {
|
||||||
PrivateKey {
|
PrivateKey { compressed: false, network, inner: key }
|
||||||
compressed: false,
|
|
||||||
network,
|
|
||||||
inner: key,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a public key from this private key
|
/// Creates a public key from this private key
|
||||||
pub fn public_key<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> PublicKey {
|
pub fn public_key<C: secp256k1::Signing>(&self, secp: &Secp256k1<C>) -> PublicKey {
|
||||||
PublicKey {
|
PublicKey {
|
||||||
compressed: self.compressed,
|
compressed: self.compressed,
|
||||||
inner: secp256k1::PublicKey::from_secret_key(secp, &self.inner)
|
inner: secp256k1::PublicKey::from_secret_key(secp, &self.inner),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serialize the private key to bytes
|
/// Serialize the private key to bytes
|
||||||
pub fn to_bytes(self) -> Vec<u8> {
|
pub fn to_bytes(self) -> Vec<u8> { self.inner[..].to_vec() }
|
||||||
self.inner[..].to_vec()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Deserialize a private key from a slice
|
/// Deserialize a private key from a slice
|
||||||
pub fn from_slice(data: &[u8], network: Network) -> Result<PrivateKey, Error> {
|
pub fn from_slice(data: &[u8], network: Network) -> Result<PrivateKey, Error> {
|
||||||
|
@ -395,7 +368,7 @@ impl PrivateKey {
|
||||||
let network = match data[0] {
|
let network = match data[0] {
|
||||||
128 => Network::Bitcoin,
|
128 => Network::Bitcoin,
|
||||||
239 => Network::Testnet,
|
239 => Network::Testnet,
|
||||||
x => {
|
x => {
|
||||||
return Err(Error::Base58(base58::Error::InvalidAddressVersion(x)));
|
return Err(Error::Base58(base58::Error::InvalidAddressVersion(x)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -409,30 +382,22 @@ impl PrivateKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for PrivateKey {
|
impl fmt::Display for PrivateKey {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_wif(f) }
|
||||||
self.fmt_wif(f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
impl fmt::Debug for PrivateKey {
|
impl fmt::Debug for PrivateKey {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[private key data]") }
|
||||||
write!(f, "[private key data]")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for PrivateKey {
|
impl FromStr for PrivateKey {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
fn from_str(s: &str) -> Result<PrivateKey, Error> {
|
fn from_str(s: &str) -> Result<PrivateKey, Error> { PrivateKey::from_wif(s) }
|
||||||
PrivateKey::from_wif(s)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ops::Index<ops::RangeFull> for PrivateKey {
|
impl ops::Index<ops::RangeFull> for PrivateKey {
|
||||||
type Output = [u8];
|
type Output = [u8];
|
||||||
fn index(&self, _: ops::RangeFull) -> &[u8] {
|
fn index(&self, _: ops::RangeFull) -> &[u8] { &self.inner[..] }
|
||||||
&self.inner[..]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
|
@ -559,15 +524,11 @@ pub type UntweakedPublicKey = XOnlyPublicKey;
|
||||||
pub struct TweakedPublicKey(XOnlyPublicKey);
|
pub struct TweakedPublicKey(XOnlyPublicKey);
|
||||||
|
|
||||||
impl fmt::LowerHex for TweakedPublicKey {
|
impl fmt::LowerHex for TweakedPublicKey {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
|
||||||
fmt::LowerHex::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for TweakedPublicKey {
|
impl fmt::Display for TweakedPublicKey {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||||
fmt::Display::fmt(&self.0, f)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Untweaked BIP-340 key pair
|
/// Untweaked BIP-340 key pair
|
||||||
|
@ -613,7 +574,11 @@ pub trait TapTweak {
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The tweaked key and its parity.
|
/// The tweaked key and its parity.
|
||||||
fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapNodeHash>) -> Self::TweakedAux;
|
fn tap_tweak<C: Verification>(
|
||||||
|
self,
|
||||||
|
secp: &Secp256k1<C>,
|
||||||
|
merkle_root: Option<TapNodeHash>,
|
||||||
|
) -> Self::TweakedAux;
|
||||||
|
|
||||||
/// Directly converts an [`UntweakedPublicKey`] to a [`TweakedPublicKey`]
|
/// Directly converts an [`UntweakedPublicKey`] to a [`TweakedPublicKey`]
|
||||||
///
|
///
|
||||||
|
@ -638,7 +603,11 @@ impl TapTweak for UntweakedPublicKey {
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The tweaked key and its parity.
|
/// The tweaked key and its parity.
|
||||||
fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapNodeHash>) -> (TweakedPublicKey, Parity) {
|
fn tap_tweak<C: Verification>(
|
||||||
|
self,
|
||||||
|
secp: &Secp256k1<C>,
|
||||||
|
merkle_root: Option<TapNodeHash>,
|
||||||
|
) -> (TweakedPublicKey, Parity) {
|
||||||
let tweak = TapTweakHash::from_key_and_tweak(self, merkle_root).to_scalar();
|
let tweak = TapTweakHash::from_key_and_tweak(self, merkle_root).to_scalar();
|
||||||
let (output_key, parity) = self.add_tweak(secp, &tweak).expect("Tap tweak failed");
|
let (output_key, parity) = self.add_tweak(secp, &tweak).expect("Tap tweak failed");
|
||||||
|
|
||||||
|
@ -646,9 +615,7 @@ impl TapTweak for UntweakedPublicKey {
|
||||||
(TweakedPublicKey(output_key), parity)
|
(TweakedPublicKey(output_key), parity)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dangerous_assume_tweaked(self) -> TweakedPublicKey {
|
fn dangerous_assume_tweaked(self) -> TweakedPublicKey { TweakedPublicKey(self) }
|
||||||
TweakedPublicKey(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TapTweak for UntweakedKeyPair {
|
impl TapTweak for UntweakedKeyPair {
|
||||||
|
@ -667,16 +634,18 @@ impl TapTweak for UntweakedKeyPair {
|
||||||
///
|
///
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The tweaked key and its parity.
|
/// The tweaked key and its parity.
|
||||||
fn tap_tweak<C: Verification>(self, secp: &Secp256k1<C>, merkle_root: Option<TapNodeHash>) -> TweakedKeyPair {
|
fn tap_tweak<C: Verification>(
|
||||||
|
self,
|
||||||
|
secp: &Secp256k1<C>,
|
||||||
|
merkle_root: Option<TapNodeHash>,
|
||||||
|
) -> TweakedKeyPair {
|
||||||
let (pubkey, _parity) = XOnlyPublicKey::from_keypair(&self);
|
let (pubkey, _parity) = XOnlyPublicKey::from_keypair(&self);
|
||||||
let tweak = TapTweakHash::from_key_and_tweak(pubkey, merkle_root).to_scalar();
|
let tweak = TapTweakHash::from_key_and_tweak(pubkey, merkle_root).to_scalar();
|
||||||
let tweaked = self.add_xonly_tweak(secp, &tweak).expect("Tap tweak failed");
|
let tweaked = self.add_xonly_tweak(secp, &tweak).expect("Tap tweak failed");
|
||||||
TweakedKeyPair(tweaked)
|
TweakedKeyPair(tweaked)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dangerous_assume_tweaked(self) -> TweakedKeyPair {
|
fn dangerous_assume_tweaked(self) -> TweakedKeyPair { TweakedKeyPair(self) }
|
||||||
TweakedKeyPair(self)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TweakedPublicKey {
|
impl TweakedPublicKey {
|
||||||
|
@ -698,17 +667,13 @@ impl TweakedPublicKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the underlying public key.
|
/// Returns the underlying public key.
|
||||||
pub fn to_inner(self) -> XOnlyPublicKey {
|
pub fn to_inner(self) -> XOnlyPublicKey { self.0 }
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Serialize the key as a byte-encoded pair of values. In compressed form
|
/// Serialize the key as a byte-encoded pair of values. In compressed form
|
||||||
/// the y-coordinate is represented by only a single bit, as x determines
|
/// the y-coordinate is represented by only a single bit, as x determines
|
||||||
/// it up to one bit.
|
/// it up to one bit.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] {
|
pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] { self.0.serialize() }
|
||||||
self.0.serialize()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TweakedKeyPair {
|
impl TweakedKeyPair {
|
||||||
|
@ -718,15 +683,11 @@ impl TweakedKeyPair {
|
||||||
/// This method is dangerous and can lead to loss of funds if used incorrectly.
|
/// This method is dangerous and can lead to loss of funds if used incorrectly.
|
||||||
/// Specifically, in multi-party protocols a peer can provide a value that allows them to steal.
|
/// Specifically, in multi-party protocols a peer can provide a value that allows them to steal.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn dangerous_assume_tweaked(pair: KeyPair) -> TweakedKeyPair {
|
pub fn dangerous_assume_tweaked(pair: KeyPair) -> TweakedKeyPair { TweakedKeyPair(pair) }
|
||||||
TweakedKeyPair(pair)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the underlying key pair.
|
/// Returns the underlying key pair.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_inner(self) -> KeyPair {
|
pub fn to_inner(self) -> KeyPair { self.0 }
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the [`TweakedPublicKey`] and its [`Parity`] for this [`TweakedKeyPair`].
|
/// Returns the [`TweakedPublicKey`] and its [`Parity`] for this [`TweakedKeyPair`].
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -738,43 +699,36 @@ impl TweakedKeyPair {
|
||||||
|
|
||||||
impl From<TweakedPublicKey> for XOnlyPublicKey {
|
impl From<TweakedPublicKey> for XOnlyPublicKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(pair: TweakedPublicKey) -> Self {
|
fn from(pair: TweakedPublicKey) -> Self { pair.0 }
|
||||||
pair.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TweakedKeyPair> for KeyPair {
|
impl From<TweakedKeyPair> for KeyPair {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(pair: TweakedKeyPair) -> Self {
|
fn from(pair: TweakedKeyPair) -> Self { pair.0 }
|
||||||
pair.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TweakedKeyPair> for TweakedPublicKey {
|
impl From<TweakedKeyPair> for TweakedPublicKey {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(pair: TweakedKeyPair) -> Self {
|
fn from(pair: TweakedKeyPair) -> Self { TweakedPublicKey::from_keypair(pair) }
|
||||||
TweakedPublicKey::from_keypair(pair)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
|
||||||
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use secp256k1::Secp256k1;
|
use secp256k1::Secp256k1;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
use crate::address::Address;
|
use crate::address::Address;
|
||||||
use crate::hashes::hex::FromHex;
|
use crate::hashes::hex::FromHex;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::network::constants::Network::Testnet;
|
use crate::network::constants::Network::{Bitcoin, Testnet};
|
||||||
use crate::network::constants::Network::Bitcoin;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_key_derivation() {
|
fn test_key_derivation() {
|
||||||
// testnet compressed
|
// testnet compressed
|
||||||
let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
|
let sk =
|
||||||
|
PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap();
|
||||||
assert_eq!(sk.network, Testnet);
|
assert_eq!(sk.network, Testnet);
|
||||||
assert!(sk.compressed);
|
assert!(sk.compressed);
|
||||||
assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
|
assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy");
|
||||||
|
@ -790,7 +744,8 @@ mod tests {
|
||||||
assert_eq!(&sk.to_wif(), &sk_str.to_wif());
|
assert_eq!(&sk.to_wif(), &sk_str.to_wif());
|
||||||
|
|
||||||
// mainnet uncompressed
|
// mainnet uncompressed
|
||||||
let sk = PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap();
|
let sk =
|
||||||
|
PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap();
|
||||||
assert_eq!(sk.network, Bitcoin);
|
assert_eq!(sk.network, Bitcoin);
|
||||||
assert!(!sk.compressed);
|
assert!(!sk.compressed);
|
||||||
assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3");
|
assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3");
|
||||||
|
@ -803,13 +758,25 @@ mod tests {
|
||||||
let addr = Address::p2pkh(&pk, sk.network);
|
let addr = Address::p2pkh(&pk, sk.network);
|
||||||
assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8");
|
assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8");
|
||||||
pk.compressed = true;
|
pk.compressed = true;
|
||||||
assert_eq!(&pk.to_string(), "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af");
|
assert_eq!(
|
||||||
assert_eq!(pk, PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap());
|
&pk.to_string(),
|
||||||
|
"032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
pk,
|
||||||
|
PublicKey::from_str(
|
||||||
|
"032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_pubkey_hash() {
|
fn test_pubkey_hash() {
|
||||||
let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
|
let pk = PublicKey::from_str(
|
||||||
|
"032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
|
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
|
||||||
assert_eq!(pk.pubkey_hash().to_string(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
assert_eq!(pk.pubkey_hash().to_string(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
||||||
assert_eq!(upk.pubkey_hash().to_string(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a");
|
assert_eq!(upk.pubkey_hash().to_string(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a");
|
||||||
|
@ -817,16 +784,22 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_wpubkey_hash() {
|
fn test_wpubkey_hash() {
|
||||||
let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap();
|
let pk = PublicKey::from_str(
|
||||||
|
"032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
|
let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap();
|
||||||
assert_eq!(pk.wpubkey_hash().unwrap().to_string(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4");
|
assert_eq!(
|
||||||
|
pk.wpubkey_hash().unwrap().to_string(),
|
||||||
|
"9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4"
|
||||||
|
);
|
||||||
assert_eq!(upk.wpubkey_hash(), None);
|
assert_eq!(upk.wpubkey_hash(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_key_serde() {
|
fn test_key_serde() {
|
||||||
use serde_test::{Configure, Token, assert_tokens};
|
use serde_test::{assert_tokens, Configure, Token};
|
||||||
|
|
||||||
static KEY_WIF: &str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy";
|
static KEY_WIF: &str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy";
|
||||||
static PK_STR: &str = "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef";
|
static PK_STR: &str = "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef";
|
||||||
|
@ -859,10 +832,7 @@ mod tests {
|
||||||
let s = Secp256k1::new();
|
let s = Secp256k1::new();
|
||||||
let sk = PrivateKey::from_str(KEY_WIF).unwrap();
|
let sk = PrivateKey::from_str(KEY_WIF).unwrap();
|
||||||
let pk = PublicKey::from_private_key(&s, &sk);
|
let pk = PublicKey::from_private_key(&s, &sk);
|
||||||
let pk_u = PublicKey {
|
let pk_u = PublicKey { inner: pk.inner, compressed: false };
|
||||||
inner: pk.inner,
|
|
||||||
compressed: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]);
|
assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]);
|
||||||
assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]);
|
assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]);
|
||||||
|
@ -922,26 +892,29 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pubkey_to_sort_key() {
|
fn pubkey_to_sort_key() {
|
||||||
let key1 = PublicKey::from_str("02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8").unwrap();
|
let key1 = PublicKey::from_str(
|
||||||
let key2 = PublicKey {
|
"02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8",
|
||||||
inner: key1.inner,
|
)
|
||||||
compressed: false,
|
.unwrap();
|
||||||
};
|
let key2 = PublicKey { inner: key1.inner, compressed: false };
|
||||||
let expected1 = SortKey(
|
let expected1 = SortKey(
|
||||||
2,
|
2,
|
||||||
<[u8; 32]>::from_hex(
|
<[u8; 32]>::from_hex(
|
||||||
"ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8",
|
"ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8",
|
||||||
).unwrap(),
|
)
|
||||||
|
.unwrap(),
|
||||||
[0_u8; 32],
|
[0_u8; 32],
|
||||||
);
|
);
|
||||||
let expected2 = SortKey(
|
let expected2 = SortKey(
|
||||||
4,
|
4,
|
||||||
<[u8; 32]>::from_hex(
|
<[u8; 32]>::from_hex(
|
||||||
"ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8",
|
"ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8",
|
||||||
).unwrap(),
|
)
|
||||||
|
.unwrap(),
|
||||||
<[u8; 32]>::from_hex(
|
<[u8; 32]>::from_hex(
|
||||||
"1794e7f3d5e420641a3bc690067df5541470c966cbca8c694bf39aa16d836918",
|
"1794e7f3d5e420641a3bc690067df5541470c966cbca8c694bf39aa16d836918",
|
||||||
).unwrap(),
|
)
|
||||||
|
.unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(key1.to_sort_key(), expected1);
|
assert_eq!(key1.to_sort_key(), expected1);
|
||||||
assert_eq!(key2.to_sort_key(), expected2);
|
assert_eq!(key2.to_sort_key(), expected2);
|
||||||
|
@ -953,9 +926,8 @@ mod tests {
|
||||||
input: Vec<PublicKey>,
|
input: Vec<PublicKey>,
|
||||||
expect: Vec<PublicKey>,
|
expect: Vec<PublicKey>,
|
||||||
}
|
}
|
||||||
let fmt = |v: Vec<_>| v.into_iter()
|
let fmt =
|
||||||
.map(|s| PublicKey::from_str(s).unwrap())
|
|v: Vec<_>| v.into_iter().map(|s| PublicKey::from_str(s).unwrap()).collect::<Vec<_>>();
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let vectors = vec![
|
let vectors = vec![
|
||||||
// Start BIP67 vectors
|
// Start BIP67 vectors
|
||||||
// Vector 1
|
// Vector 1
|
||||||
|
|
|
@ -14,14 +14,14 @@
|
||||||
use core::borrow::{Borrow, BorrowMut};
|
use core::borrow::{Borrow, BorrowMut};
|
||||||
use core::{fmt, str};
|
use core::{fmt, str};
|
||||||
|
|
||||||
use crate::{io, Script, ScriptBuf, Transaction, TxIn, TxOut, Sequence};
|
|
||||||
use crate::blockdata::transaction::EncodeSigningDataResult;
|
use crate::blockdata::transaction::EncodeSigningDataResult;
|
||||||
use crate::blockdata::witness::Witness;
|
use crate::blockdata::witness::Witness;
|
||||||
use crate::consensus::{encode, Encodable};
|
use crate::consensus::{encode, Encodable};
|
||||||
use crate::error::impl_std_error;
|
use crate::error::impl_std_error;
|
||||||
use crate::hashes::{hash_newtype, sha256, sha256t_hash_newtype, sha256d, Hash};
|
use crate::hashes::{hash_newtype, sha256, sha256d, sha256t_hash_newtype, Hash};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX};
|
use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX};
|
||||||
|
use crate::{io, Script, ScriptBuf, Sequence, Transaction, TxIn, TxOut};
|
||||||
|
|
||||||
/// Used for signature hash for invalid use of SIGHASH_SINGLE.
|
/// Used for signature hash for invalid use of SIGHASH_SINGLE.
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -44,7 +44,7 @@ macro_rules! impl_thirty_two_byte_hash {
|
||||||
impl secp256k1::ThirtyTwoByteHash for $ty {
|
impl secp256k1::ThirtyTwoByteHash for $ty {
|
||||||
fn into_32(self) -> [u8; 32] { self.to_byte_array() }
|
fn into_32(self) -> [u8; 32] { self.to_byte_array() }
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_newtype! {
|
hash_newtype! {
|
||||||
|
@ -60,10 +60,15 @@ hash_newtype! {
|
||||||
impl_thirty_two_byte_hash!(LegacySighash);
|
impl_thirty_two_byte_hash!(LegacySighash);
|
||||||
impl_thirty_two_byte_hash!(SegwitV0Sighash);
|
impl_thirty_two_byte_hash!(SegwitV0Sighash);
|
||||||
|
|
||||||
sha256t_hash_newtype!(TapSighash, TapSighashTag, MIDSTATE_TAPSIGHASH, 64,
|
sha256t_hash_newtype!(
|
||||||
doc="Taproot-tagged hash with tag \"TapSighash\".
|
TapSighash,
|
||||||
|
TapSighashTag,
|
||||||
|
MIDSTATE_TAPSIGHASH,
|
||||||
|
64,
|
||||||
|
doc = "Taproot-tagged hash with tag \"TapSighash\".
|
||||||
|
|
||||||
This hash type is used for computing taproot signature hash.", forward
|
This hash type is used for computing taproot signature hash.",
|
||||||
|
forward
|
||||||
);
|
);
|
||||||
|
|
||||||
impl_thirty_two_byte_hash!(TapSighash);
|
impl_thirty_two_byte_hash!(TapSighash);
|
||||||
|
@ -559,14 +564,10 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the reference to the cached transaction.
|
/// Returns the reference to the cached transaction.
|
||||||
pub fn transaction(&self) -> &Transaction {
|
pub fn transaction(&self) -> &Transaction { self.tx.borrow() }
|
||||||
self.tx.borrow()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Destroys the cache and recovers the stored transaction.
|
/// Destroys the cache and recovers the stored transaction.
|
||||||
pub fn into_transaction(self) -> R {
|
pub fn into_transaction(self) -> R { self.tx }
|
||||||
self.tx
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encodes the BIP341 signing data for any flag type into a given object implementing a
|
/// Encodes the BIP341 signing data for any flag type into a given object implementing a
|
||||||
/// [`io::Write`] trait.
|
/// [`io::Write`] trait.
|
||||||
|
@ -633,10 +634,11 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
// scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes.
|
// scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes.
|
||||||
// nSequence (4): nSequence of this input.
|
// nSequence (4): nSequence of this input.
|
||||||
if anyone_can_pay {
|
if anyone_can_pay {
|
||||||
let txin = &self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds {
|
let txin =
|
||||||
index: input_index,
|
&self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds {
|
||||||
inputs_size: self.tx.borrow().input.len(),
|
index: input_index,
|
||||||
})?;
|
inputs_size: self.tx.borrow().input.len(),
|
||||||
|
})?;
|
||||||
let previous_output = prevouts.get(input_index)?;
|
let previous_output = prevouts.get(input_index)?;
|
||||||
txin.previous_output.consensus_encode(&mut writer)?;
|
txin.previous_output.consensus_encode(&mut writer)?;
|
||||||
previous_output.value.consensus_encode(&mut writer)?;
|
previous_output.value.consensus_encode(&mut writer)?;
|
||||||
|
@ -782,10 +784,11 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let txin = &self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds {
|
let txin =
|
||||||
index: input_index,
|
&self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds {
|
||||||
inputs_size: self.tx.borrow().input.len(),
|
index: input_index,
|
||||||
})?;
|
inputs_size: self.tx.borrow().input.len(),
|
||||||
|
})?;
|
||||||
|
|
||||||
txin.previous_output.consensus_encode(&mut writer)?;
|
txin.previous_output.consensus_encode(&mut writer)?;
|
||||||
script_code.consensus_encode(&mut writer)?;
|
script_code.consensus_encode(&mut writer)?;
|
||||||
|
@ -795,7 +798,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
|
|
||||||
if sighash != EcdsaSighashType::Single && sighash != EcdsaSighashType::None {
|
if sighash != EcdsaSighashType::Single && sighash != EcdsaSighashType::None {
|
||||||
self.segwit_cache().outputs.consensus_encode(&mut writer)?;
|
self.segwit_cache().outputs.consensus_encode(&mut writer)?;
|
||||||
} else if sighash == EcdsaSighashType::Single && input_index < self.tx.borrow().output.len() {
|
} else if sighash == EcdsaSighashType::Single && input_index < self.tx.borrow().output.len()
|
||||||
|
{
|
||||||
let mut single_enc = LegacySighash::engine();
|
let mut single_enc = LegacySighash::engine();
|
||||||
self.tx.borrow().output[input_index].consensus_encode(&mut single_enc)?;
|
self.tx.borrow().output[input_index].consensus_encode(&mut single_enc)?;
|
||||||
let hash = LegacySighash::from_engine(single_enc);
|
let hash = LegacySighash::from_engine(single_enc);
|
||||||
|
@ -865,7 +869,11 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
||||||
}
|
}
|
||||||
let sighash_type: u32 = sighash_type.into();
|
let sighash_type: u32 = sighash_type.into();
|
||||||
|
|
||||||
if is_invalid_use_of_sighash_single(sighash_type, input_index, self.tx.borrow().output.len()) {
|
if is_invalid_use_of_sighash_single(
|
||||||
|
sighash_type,
|
||||||
|
input_index,
|
||||||
|
self.tx.borrow().output.len(),
|
||||||
|
) {
|
||||||
// We cannot correctly handle the SIGHASH_SINGLE bug here because usage of this function
|
// We cannot correctly handle the SIGHASH_SINGLE bug here because usage of this function
|
||||||
// will result in the data written to the writer being hashed, however the correct
|
// will result in the data written to the writer being hashed, however the correct
|
||||||
// handling of the SIGHASH_SINGLE bug is to return the 'one array' - either implement
|
// handling of the SIGHASH_SINGLE bug is to return the 'one array' - either implement
|
||||||
|
@ -1197,8 +1205,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_tap_sighash_hash() {
|
fn test_tap_sighash_hash() {
|
||||||
let bytes = hex!("00011b96877db45ffa23b307e9f0ac87b80ef9a80b4c5f0db3fbe734422453e83cc5576f3d542c5d4898fb2b696c15d43332534a7c1d1255fda38993545882df92c3e353ff6d36fbfadc4d168452afd8467f02fe53d71714fcea5dfe2ea759bd00185c4cb02bc76d42620393ca358a1a713f4997f9fc222911890afb3fe56c6a19b202df7bffdcfad08003821294279043746631b00e2dc5e52a111e213bbfe6ef09a19428d418dab0d50000000000");
|
let bytes = hex!("00011b96877db45ffa23b307e9f0ac87b80ef9a80b4c5f0db3fbe734422453e83cc5576f3d542c5d4898fb2b696c15d43332534a7c1d1255fda38993545882df92c3e353ff6d36fbfadc4d168452afd8467f02fe53d71714fcea5dfe2ea759bd00185c4cb02bc76d42620393ca358a1a713f4997f9fc222911890afb3fe56c6a19b202df7bffdcfad08003821294279043746631b00e2dc5e52a111e213bbfe6ef09a19428d418dab0d50000000000");
|
||||||
let expected =
|
let expected = hex!("04e808aad07a40b3767a1442fead79af6ef7e7c9316d82dec409bb31e77699b0");
|
||||||
hex!("04e808aad07a40b3767a1442fead79af6ef7e7c9316d82dec409bb31e77699b0");
|
|
||||||
let mut enc = TapSighash::engine();
|
let mut enc = TapSighash::engine();
|
||||||
enc.input(&bytes);
|
enc.input(&bytes);
|
||||||
let hash = TapSighash::from_engine(enc);
|
let hash = TapSighash::from_engine(enc);
|
||||||
|
@ -1690,22 +1697,27 @@ mod tests {
|
||||||
let mut cache = SighashCache::new(&tx);
|
let mut cache = SighashCache::new(&tx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.segwit_signature_hash(1, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
cache.segwit_signature_hash(1, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
||||||
"c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670".parse::<SegwitV0Sighash>().unwrap(),
|
"c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670"
|
||||||
|
.parse::<SegwitV0Sighash>()
|
||||||
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let cache = cache.segwit_cache();
|
let cache = cache.segwit_cache();
|
||||||
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.prevouts.as_byte_array(),
|
cache.prevouts.as_byte_array(),
|
||||||
&Vec::from_hex("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37").unwrap()[..],
|
&Vec::from_hex("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.sequences.as_byte_array(),
|
cache.sequences.as_byte_array(),
|
||||||
&Vec::from_hex("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b").unwrap()[..],
|
&Vec::from_hex("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.outputs.as_byte_array(),
|
cache.outputs.as_byte_array(),
|
||||||
&Vec::from_hex("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5").unwrap()[..],
|
&Vec::from_hex("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1726,33 +1738,38 @@ mod tests {
|
||||||
let mut cache = SighashCache::new(&tx);
|
let mut cache = SighashCache::new(&tx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
||||||
"64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6".parse::<SegwitV0Sighash>().unwrap(),
|
"64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6"
|
||||||
|
.parse::<SegwitV0Sighash>()
|
||||||
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let cache = cache.segwit_cache();
|
let cache = cache.segwit_cache();
|
||||||
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.prevouts.as_byte_array(),
|
cache.prevouts.as_byte_array(),
|
||||||
&Vec::from_hex("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a").unwrap()[..],
|
&Vec::from_hex("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.sequences.as_byte_array(),
|
cache.sequences.as_byte_array(),
|
||||||
&Vec::from_hex("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198").unwrap()[..],
|
&Vec::from_hex("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.outputs.as_byte_array(),
|
cache.outputs.as_byte_array(),
|
||||||
&Vec::from_hex("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83").unwrap()[..],
|
&Vec::from_hex("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bip143_p2wsh_nested_in_p2sh() {
|
fn bip143_p2wsh_nested_in_p2sh() {
|
||||||
let tx = deserialize::<Transaction>(
|
let tx = deserialize::<Transaction>(&hex!(
|
||||||
&hex!(
|
|
||||||
"010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000\
|
"010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000\
|
||||||
ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f\
|
ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f\
|
||||||
05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"),
|
05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"
|
||||||
).unwrap();
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let witness_script = ScriptBuf::from_hex(
|
let witness_script = ScriptBuf::from_hex(
|
||||||
"56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\
|
"56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\
|
||||||
|
@ -1760,29 +1777,35 @@ mod tests {
|
||||||
9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\
|
9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\
|
||||||
c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b1486\
|
c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b1486\
|
||||||
2c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b\
|
2c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b\
|
||||||
56ae"
|
56ae",
|
||||||
).unwrap();
|
)
|
||||||
|
.unwrap();
|
||||||
let value = 987654321;
|
let value = 987654321;
|
||||||
|
|
||||||
let mut cache = SighashCache::new(&tx);
|
let mut cache = SighashCache::new(&tx);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(),
|
||||||
"185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c".parse::<SegwitV0Sighash>().unwrap(),
|
"185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c"
|
||||||
|
.parse::<SegwitV0Sighash>()
|
||||||
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let cache = cache.segwit_cache();
|
let cache = cache.segwit_cache();
|
||||||
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
// Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.prevouts.as_byte_array(),
|
cache.prevouts.as_byte_array(),
|
||||||
&Vec::from_hex("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0").unwrap()[..],
|
&Vec::from_hex("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.sequences.as_byte_array(),
|
cache.sequences.as_byte_array(),
|
||||||
&Vec::from_hex("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044").unwrap()[..],
|
&Vec::from_hex("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
cache.outputs.as_byte_array(),
|
cache.outputs.as_byte_array(),
|
||||||
&Vec::from_hex("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc").unwrap()[..],
|
&Vec::from_hex("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc")
|
||||||
|
.unwrap()[..],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,9 @@
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use bitcoin_internals::write_err;
|
use bitcoin_internals::write_err;
|
||||||
|
pub use secp256k1::{self, constants, KeyPair, Parity, Secp256k1, Verification, XOnlyPublicKey};
|
||||||
pub use secp256k1::{self, constants, Secp256k1, KeyPair, XOnlyPublicKey, Verification, Parity};
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::sighash::TapSighashType;
|
use crate::sighash::TapSighashType;
|
||||||
|
|
||||||
/// A BIP340-341 serialized taproot signature with the corresponding hash type.
|
/// A BIP340-341 serialized taproot signature with the corresponding hash type.
|
||||||
|
@ -33,21 +31,19 @@ impl Signature {
|
||||||
match sl.len() {
|
match sl.len() {
|
||||||
64 => {
|
64 => {
|
||||||
// default type
|
// default type
|
||||||
let sig = secp256k1::schnorr::Signature::from_slice(sl)
|
let sig =
|
||||||
.map_err(Error::Secp256k1)?;
|
secp256k1::schnorr::Signature::from_slice(sl).map_err(Error::Secp256k1)?;
|
||||||
Ok(Signature { sig, hash_ty: TapSighashType::Default })
|
Ok(Signature { sig, hash_ty: TapSighashType::Default })
|
||||||
},
|
}
|
||||||
65 => {
|
65 => {
|
||||||
let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65");
|
let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65");
|
||||||
let hash_ty = TapSighashType::from_consensus_u8(*hash_ty)
|
let hash_ty = TapSighashType::from_consensus_u8(*hash_ty)
|
||||||
.map_err(|_| Error::InvalidSighashType(*hash_ty))?;
|
.map_err(|_| Error::InvalidSighashType(*hash_ty))?;
|
||||||
let sig = secp256k1::schnorr::Signature::from_slice(sig)
|
let sig =
|
||||||
.map_err(Error::Secp256k1)?;
|
secp256k1::schnorr::Signature::from_slice(sig).map_err(Error::Secp256k1)?;
|
||||||
Ok(Signature { sig, hash_ty })
|
Ok(Signature { sig, hash_ty })
|
||||||
}
|
}
|
||||||
len => {
|
len => Err(Error::InvalidSignatureSize(len)),
|
||||||
Err(Error::InvalidSignatureSize(len))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +58,6 @@ impl Signature {
|
||||||
}
|
}
|
||||||
ser_sig
|
ser_sig
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A taproot sig related error.
|
/// A taproot sig related error.
|
||||||
|
@ -77,7 +72,6 @@ pub enum Error {
|
||||||
InvalidSignatureSize(usize),
|
InvalidSignatureSize(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -85,8 +79,7 @@ impl fmt::Display for Error {
|
||||||
write!(f, "invalid signature hash type {}", hash_ty),
|
write!(f, "invalid signature hash type {}", hash_ty),
|
||||||
Error::Secp256k1(ref e) =>
|
Error::Secp256k1(ref e) =>
|
||||||
write_err!(f, "taproot signature has correct len but is malformed"; e),
|
write_err!(f, "taproot signature has correct len but is malformed"; e),
|
||||||
Error::InvalidSignatureSize(sz) =>
|
Error::InvalidSignatureSize(sz) => write!(f, "invalid taproot signature size: {}", sz),
|
||||||
write!(f, "invalid taproot signature size: {}", sz),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,8 +98,5 @@ impl std::error::Error for Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<secp256k1::Error> for Error {
|
impl From<secp256k1::Error> for Error {
|
||||||
|
fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) }
|
||||||
fn from(e: secp256k1::Error) -> Error {
|
|
||||||
Error::Secp256k1(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue